The light shader in ch05

Hi, I’m curious about the light shader provided in ch05.

 fragment float4 fragment_light(float2 point [[ point_coord]],
                                constant float3 &color [[ buffer(1) ]]) {
   float d = distance(point, float2(0.5, 0.5));
   if (d > 0.5) {
     discard_fragment();
   }
   return float4(color ,1);
 }

I’m not sure what the point variable refer to. My understand is this is one pixel that on the screen. So here I don’t understand what the point(0.5,0.5) is

That isn’t really a “light” shader - it’s the debug shader. It shows a red circle where a point light is.

And the point variable isn’t necessarily one pixel, you specify the size using a property with the [[point_size]] attribute. That’s in VertexOut and set to 20.0 in the vertex shader. You used points at the beginning of chapter 4 to try out transforms. You can look at the shader in the Chapter 4 Playground 3DTransforms to see how that works.

So without the discard_fragment() bit, the debug shader would show a red square rather than a circle.

The fragment shader receives the fragment it’s going to render within that red square. That’s the [[point_coord]] attribute, which is from 0 to 1. 0, 0 being the top left of the red square and 1,1 being the bottom right.

So a circle in that square would have a radius of 0.5. By checking whether the distance of the fragment is further than 0.5, you’re checking to see if it’s outside the circle (ie in the corner of the square). If it is, discard it, and you’re left with a red circle instead of a red square.

Rendering points can be quite useful aside from this debugging. They are 2D and very fast to render. Much later on, when rendering particles, you’ll use large points to render a texture on to. You can use them for billboard textures that always face the camera. For example, if you wanted to render a 2d tree in the background for speed, you could render a texture onto a point, and the tree would always face the camera.

Try changing point_size in the vertex shader, vertex_light, to something huge, like 150, make sure you’re debug rendering point lights in Renderer.swift:

 debugLights(renderEncoder: renderEncoder, lightType: Pointlight)

and change the shader to this:

fragment float4 fragment_light(float2 point [[ point_coord]],
                               constant float3 &color [[ buffer(1) ]]) {
  float d = distance(point, float2(0.5, 0.5));
//  if (d > 0.5) {
//    discard_fragment();
//  }
  if (point.x <= 0.2 && point.y <= 0.2) {
    return float4(0, 1, 0, 1);
  }
  return float4(color ,1);

You’ll find that the top left of the resulting red square is rendered in green.

Btw, to format code, you use back ticks ```

One back tick surrounding the text looks like this.

Three back ticks surrounding a block looks like this

thank you,

 .point_size=20

seems only affect the result when set type to .point in

 renderEncoder.drawPrimitives(type: .lineStrip, vertexStart: 0, vertexCount: vertices.count)

if I want to render a line with width ,what can I do


Here I try to compare the examples in 3 chapter

That debug light shader is used by the encoder in DebugLights.swift.

renderEncoder.drawPrimitives(type: .point, vertexStart: 0,
                             vertexCount: vertices.count) 

So you have to set the draw type to .point.

Unfortunately rendering lines with width on the GPU is really really hard.

Here’s an article on the theory of it (it’s OpenGL, but concepts are generally similar): https://mattdesl.svbtle.com/drawing-lines-is-hard. He suggests “…break a line into triangles or triangle strips, and then render them as regular geometry.”

ok, I decide not to research this for now until I have accumulate enough knowledge,
thank you

Good thinking :+1:. The amount to learn is overwhelming at the start, but stick with it as it gets easier!