为什么模板测试不丢弃片段?
Why stencil test does not discard fragments?
我想 运行 模板测试来勾勒立方体的轮廓。来自learnopengl https://learnopengl.com/Advanced-OpenGL/Stencil-testing。
做轮廓处理的立方体应该丢弃了纹理立方体上的碎片。它不会发生,轮廓立方体覆盖了整个区域。
static const char* cubeVtx = R"(
#version 460 core
layout (location = 0) in vec3 a_position;
layout (location = 1) in vec2 a_uv;
out vec2 v_uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
v_uv = a_uv;
gl_Position = projection * view * model * vec4(a_position, 1.0f);
}
)";
static const char* cubeFrag = R"(
#version 460 core
layout (location = 0) out vec4 f_color;
in vec2 v_uv;
uniform sampler2D u_texture1;
void main()
{
f_color = texture(u_texture1, v_uv);
}
)";
static const char* singleColorVtx = R"(
#version 460 core
layout (location = 0) in vec3 a_position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(a_position, 1.0f);
}
)";
static const char* singleColorFrag = R"(
#version 460 core
layout (location = 0) out vec4 f_color;
void main()
{
f_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
)";
void Cube::InitAPI()
{
shader = Shader::Create();
ShaderProgram program[2] = {
shader->ShaderFromSource(cubeVtx, ShaderType::Vertex),
shader->ShaderFromSource(cubeFrag, ShaderType::Fragment)
};
shader->End(program, 2);
singleColorShader = Shader::Create();
ShaderProgram singleColorProgram[2] = {
singleColorShader->ShaderFromSource(singleColorVtx, ShaderType::Vertex),
singleColorShader->ShaderFromSource(singleColorFrag, ShaderType::Fragment)
};
singleColorShader->End(singleColorProgram, 2);
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);
glCreateBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glNamedBufferData(vbo, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * sizeof(float), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glCreateVertexArrays(1, &planeVao);
glBindVertexArray(planeVao);
glCreateBuffers(1, &planeVbo);
glBindBuffer(GL_ARRAY_BUFFER, planeVbo);
glNamedBufferData(planeVbo, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * sizeof(float), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * sizeof(float), (void*)(3 * sizeof(float)));
texture = Texture::LoadPNG("Media/container2");
planeTexture = Texture::LoadPNG("Media/matrix");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
shader->UseProgram();
shader->Uniform1i("u_texture1", 0);
}
void Cube::Render()
{
singleColorShader->UseProgram();
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)1280.0f / (float)720.0f, 0.1f, 100.0f);
singleColorShader->UniformMatrix4fv("view", view);
singleColorShader->UniformMatrix4fv("projection", projection);
shader->UseProgram();
shader->UniformMatrix4fv("view", view);
shader->UniformMatrix4fv("projection", projection);
glStencilMask(0x00);
glBindVertexArray(planeVao);
planeTexture->Active();
planeTexture->Bind();
glDrawArrays(GL_TRIANGLES, 0, 6);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
glBindVertexArray(vao);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
shader->UniformMatrix4fv("model", model);
texture->Active();
texture->Bind();
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00);
glDisable(GL_DEPTH_TEST);
singleColorShader->UseProgram();
float scale = 1.1;
glBindVertexArray(vao);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
model = glm::scale(model, glm::vec3(scale, scale, scale));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(scale, scale, scale));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glStencilMask(0xFF);
glEnable(GL_DEPTH_TEST);
}
Test::Test()
{
//tried many patterns and stencil values
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
window = SDL_CreateWindow("window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);
glewExperimental = true;
glewInit();
cube.InitAPI();
}
void Test::MainLoop()
{
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
cube.Render();
SDL_GL_SwapWindow(window);
}
}
我仍然不太明白深度测试的事情,当我开始认为我正在进行模板测试时,一切都搞砸了,因为它不起作用。
是的,我在其他地方清除颜色、深度和模板缓冲区,但在 Render()
方法之前。
我得到了什么:
我期望的是红色轮廓,而不是整个立方体
你能像我是个白痴一样解释一下为什么它不丢弃 1
的片段吗
先调用 SDL_Init
,再调用任何其他 SDL-function
SDL_Init(SDL_INIT_EVERYTHING);
参见 SDL_Init()
的文档:
Use this function to initialize the SDL library. This must be called before using most other SDL functions.
要使模板缓冲区工作,必须设置 SDL_GL_STENCIL_SIZE
属性。默认情况下,此属性为 0。通常,模板缓冲区有 8 位。例如:
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute
has to be called before SDL_CreateWindow
否则没有任何作用
参见SDL_GL_SetAttribute
的文档:
Use this function to set an OpenGL window attribute before window creation.
原始代码在SDL_GL_SetAttribute()
之后调用SDL_Init
上面的代码甚至没有调用 SDL_Init
。初始化 SDL 可以解决所有问题。
我想 运行 模板测试来勾勒立方体的轮廓。来自learnopengl https://learnopengl.com/Advanced-OpenGL/Stencil-testing。
做轮廓处理的立方体应该丢弃了纹理立方体上的碎片。它不会发生,轮廓立方体覆盖了整个区域。
static const char* cubeVtx = R"(
#version 460 core
layout (location = 0) in vec3 a_position;
layout (location = 1) in vec2 a_uv;
out vec2 v_uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
v_uv = a_uv;
gl_Position = projection * view * model * vec4(a_position, 1.0f);
}
)";
static const char* cubeFrag = R"(
#version 460 core
layout (location = 0) out vec4 f_color;
in vec2 v_uv;
uniform sampler2D u_texture1;
void main()
{
f_color = texture(u_texture1, v_uv);
}
)";
static const char* singleColorVtx = R"(
#version 460 core
layout (location = 0) in vec3 a_position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(a_position, 1.0f);
}
)";
static const char* singleColorFrag = R"(
#version 460 core
layout (location = 0) out vec4 f_color;
void main()
{
f_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
)";
void Cube::InitAPI()
{
shader = Shader::Create();
ShaderProgram program[2] = {
shader->ShaderFromSource(cubeVtx, ShaderType::Vertex),
shader->ShaderFromSource(cubeFrag, ShaderType::Fragment)
};
shader->End(program, 2);
singleColorShader = Shader::Create();
ShaderProgram singleColorProgram[2] = {
singleColorShader->ShaderFromSource(singleColorVtx, ShaderType::Vertex),
singleColorShader->ShaderFromSource(singleColorFrag, ShaderType::Fragment)
};
singleColorShader->End(singleColorProgram, 2);
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);
glCreateBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glNamedBufferData(vbo, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * sizeof(float), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glCreateVertexArrays(1, &planeVao);
glBindVertexArray(planeVao);
glCreateBuffers(1, &planeVbo);
glBindBuffer(GL_ARRAY_BUFFER, planeVbo);
glNamedBufferData(planeVbo, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * sizeof(float), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * sizeof(float), (void*)(3 * sizeof(float)));
texture = Texture::LoadPNG("Media/container2");
planeTexture = Texture::LoadPNG("Media/matrix");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
shader->UseProgram();
shader->Uniform1i("u_texture1", 0);
}
void Cube::Render()
{
singleColorShader->UseProgram();
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)1280.0f / (float)720.0f, 0.1f, 100.0f);
singleColorShader->UniformMatrix4fv("view", view);
singleColorShader->UniformMatrix4fv("projection", projection);
shader->UseProgram();
shader->UniformMatrix4fv("view", view);
shader->UniformMatrix4fv("projection", projection);
glStencilMask(0x00);
glBindVertexArray(planeVao);
planeTexture->Active();
planeTexture->Bind();
glDrawArrays(GL_TRIANGLES, 0, 6);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
glBindVertexArray(vao);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
shader->UniformMatrix4fv("model", model);
texture->Active();
texture->Bind();
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00);
glDisable(GL_DEPTH_TEST);
singleColorShader->UseProgram();
float scale = 1.1;
glBindVertexArray(vao);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
model = glm::scale(model, glm::vec3(scale, scale, scale));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(scale, scale, scale));
shader->UniformMatrix4fv("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glStencilMask(0xFF);
glEnable(GL_DEPTH_TEST);
}
Test::Test()
{
//tried many patterns and stencil values
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
window = SDL_CreateWindow("window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);
glewExperimental = true;
glewInit();
cube.InitAPI();
}
void Test::MainLoop()
{
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
cube.Render();
SDL_GL_SwapWindow(window);
}
}
我仍然不太明白深度测试的事情,当我开始认为我正在进行模板测试时,一切都搞砸了,因为它不起作用。
是的,我在其他地方清除颜色、深度和模板缓冲区,但在 Render()
方法之前。
我得到了什么:
我期望的是红色轮廓,而不是整个立方体
你能像我是个白痴一样解释一下为什么它不丢弃 1
先调用 SDL_Init
,再调用任何其他 SDL-function
SDL_Init(SDL_INIT_EVERYTHING);
参见 SDL_Init()
的文档:
Use this function to initialize the SDL library. This must be called before using most other SDL functions.
要使模板缓冲区工作,必须设置 SDL_GL_STENCIL_SIZE
属性。默认情况下,此属性为 0。通常,模板缓冲区有 8 位。例如:
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute
has to be called before SDL_CreateWindow
否则没有任何作用
参见SDL_GL_SetAttribute
的文档:
Use this function to set an OpenGL window attribute before window creation.
原始代码在SDL_GL_SetAttribute()
之后调用SDL_Init
上面的代码甚至没有调用 SDL_Init
。初始化 SDL 可以解决所有问题。