Hello, I’m moving forward to the part that add depthStencil.
for purpose of comparison, I put 3 object in the scene to render
- the triangle from ch04 when add the concept of matrix
- the mushroom I create from blender and import using the new method introduced in ch05
- I also create a little helper object that indicate the origin of the scene and the length of unit 1
I capsulated each into a single class and render them one by one like below
ch04Triangle.render(renderEncoder: renderEncoder)
ch05MeshWithNormal.render(renderEncoder: renderEncoder, uniforms: &uniforms)
center.render(renderEncoder: renderEncoder, uniforms: &uniforms)
the question is the when I add depthStencil , my ch04 triangle disappeared and the center no longer sit in front of the other object
Is there any way that I can turn off depthStencil for some object(e.g. my Center object)
I’m going to use the example of the pipeline state instead of depth stencil state for the moment.
In chapter 5, you use a different pipeline state for each model. This will eventually change to a different pipeline state per submesh, depending on the type of surface material. Sometimes you need a different shader depending on the materials and you need a different pipeline state for each different shader.
This might not be the best way of doing it, but it’s difficult in a book to refactor everything all the time.
I would prefer a centralised shader controller in a real app and also ensure that my models conformed to a specific paradigm of textures etc, which I don’t enforce in this app. Later in the GPU chapter 15, we show you how to create a central heap of textures, which is more real life than holding the texture per submesh.
Going back to depth stencil states, you could create a singleton controller that holds all the depth stencil states you need for the app and pass a parameter to the model that holds the depth stencil state for that particular model. In Renderer, you’d make sure that the depth stencil state was loaded for the model, just as you currently load the pipeline state.
Or, if you have a special debug model, you could treat it as I have treated DebugLights in the Utility group, and render the model separately after all the other models have been rendered, with its own depth stencil state.
1 Like
Hi, thank you for advice.
yes, I have give each object their own shader and own pipelinestate. This works fine.
but for depthStencilState it seems did not work. The depthStencilState seems so high level in the renderEncoder. Once set there is no way to cancel it . But Inspired by the web , after 1 day of hard work I finally succeed by creating another MTLRenderPassDescriptor and set its colorAttachments[0].loadAction to .load
let pass2Descriptor = MTLRenderPassDescriptor()
pass2Descriptor.colorAttachments[0].texture = drawable.texture
pass2Descriptor.colorAttachments[0].loadAction = .load
let noDepthEncoder = commandBuffer.makeRenderCommandEncoder( descriptor: pass2Descriptor)!
center.render(renderEncoder: noDepthEncoder, uniforms: &uniforms)
noDepthEncoder.endEncoding()
I’m glad you got it working, but I’m surprised you needed a new render pass.
I tested it out with my debug sunlight line. These go through the tree and the train and disappear, but if I build a second depth stencil state:
static func buildDepthStencilState2() -> MTLDepthStencilState? {
let descriptor = MTLDepthStencilDescriptor()
descriptor.depthCompareFunction = .always
descriptor.isDepthWriteEnabled = false
return Renderer.device.makeDepthStencilState(descriptor: descriptor)
}
and in debugLights(renderEncoder:lightType:)
, before calling drawDirectionalLight(etc:)
, I added:
renderEncoder.setDepthStencilState(Self.buildDepthStencilState2())
The lines now render on top of the model.
(Btw - it’s really bad practice to build a depth stencil state on the fly like this - they should be set up at the start of the app before the draw loop)
I also facing this type of problem.
really ? I will test DepthStencilState again.
So do you mean the render pass solution is better than depthStencil for this problem?
Ok ,I success
the clause “descriptor.depthCompareFunction = .always” finally did it . No matter the descriptor.isDepthWriteEnabled = true or false.
Thanks ,always.
So the left question is what cause the sunlight lines flickering all the time?
1 Like
Well done!
The sunlight lines flicker because sometimes the lines are too thin to be drawn, so they flicker in and out. This is because of the shader code that makes the debug points into circles and remove half the fragment.
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);
}
This should make your lines thicker. If you want thick lines on lines, and the circle on points, you can set a boolean and send it as another parameter to the shader using, eg, buffer(2) and test it there. However, as you asked before, the line isn’t going to be any thicker than that unless you draw quads along it.
Changing states, such as pipeline state and depth stencil state, on the GPU is very fast. Faster than the render pass solution.
My previous comment about best practice referred to my creating the depth stencil state during the draw call. Your creation of it up front is the way to go.
@growthlyzet - Hi! Do relaxslow’s answers help you?
perfect, now i have enough knowledge to build my own helper object
1 Like
Also, as you probably realised, if you want to use a different vertex or fragment shader on your helper object, then you can use a different pipeline state.
@relaxslow Thank you for sharing your solution - much appreciated!
@growthlyzet Do you stil have issues with this?