c++ - 为什么我的三角形在镶嵌后不显示?OpenGL
问题描述
我开始学习opengl,我正处于镶嵌阶段,我有问题,当我将镶嵌着色器附加到程序中时,我的三角形不会显示。着色器编译正确,没有链接错误。从代码方面来看,一切似乎都很好。当我只使用顶点着色器和片段着色器时,一切都很好。可能是什么原因?
Shaders::Shaders(const char* vertexPath, const char* fragmentPath, const char* tessControlPath, const char* tessEvaluationPath)
{
std::string vs_str = load_file(vertexPath);
std::string fs_str = load_file(fragmentPath);
std::string tc_str = load_file(tessControlPath);
std::string te_str = load_file(tessEvaluationPath);
const char* vs_src = vs_str.c_str();
const char* fs_src = fs_str.c_str();
const char* tc_src = tc_str.c_str();
const char* te_src = te_str.c_str();
create_shader(GL_VERTEX_SHADER, vertexShader, vs_src);
create_shader(GL_FRAGMENT_SHADER, fragmentShader, fs_src);
create_shader(GL_TESS_CONTROL_SHADER, tessControlShader, tc_src);
create_shader(GL_TESS_EVALUATION_SHADER, tessEvaluationShader, te_src);
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glAttachShader(program, tessControlShader);
glAttachShader(program, tessEvaluationShader);
glLinkProgram(program);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(tessControlShader);
glDeleteShader(tessEvaluationShader);
glCreateVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
}
void Shaders::create_shader(GLenum type, GLuint& shader, const char* src)
{
GLint isCompiled = 0;
shader = glCreateShader(type);
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
for (int i = 0; i < errorLog.size(); i++)
{
std::cerr << errorLog[i];
}
glDeleteShader(shader);
}
}
int main()
{
Window* window = new Window(1200, 1000);
Shaders* shader = new Shaders("shaders/vertex.glsl", "shaders/fragment.glsl", "shaders/tess_control.glsl", "shaders/tess_evaluation.glsl");
while (glfwWindowShouldClose(window->get_window()) == false)
{
window->loop();
const GLfloat color[]{1.0f, 0.5f, 0.5f, 1.0f};
glClearBufferfv(GL_COLOR, 0, color);
const GLfloat attrib[]{0.0f, 0.0f, 1.0f, 1.0f};
glUseProgram(shader->get_program());
glVertexAttrib4fv(0, attrib);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawArrays(GL_PATCHES, 0, 3);
}
delete window;
delete shader;
glfwTerminate();
}
顶点.glsl
#version 450 core
layout (location = 0) in vec4 color;
out VS_OUT
{
vec4 color;
} vs_out;
void main(void)
{
const vec4 vertices[3] = vec4[3](vec4( 0.25, -0.25, 0.5, 1.0), vec4(-0.25, -0.25, 0.5, 1.0), vec4(0.25, 0.25, 0.5, 1.0));
gl_Position = vertices[gl_VertexID];
vs_out.color = color;
}
片段.glsl
#version 450 core
in VS_OUT
{
vec4 color;
} fs_in;
out vec4 color;
void main(void)
{
color = fs_in.color;
}
tess_control.glsl
#version 450 core
layout (vertices = 3) out;
void main(void)
{
if (gl_InvocationID = 0)
{
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 5.0;
gl_TessLevelOuter[1] = 5.0;
gl_TessLevelOuter[2] = 5.0;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
tess_evaluation.glsl
#version 450 core
layout (triangles, equal_spacing, ccw) in;
void main(void)
{
gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position);
}
解决方案
您已通过以下方式指定将用于构成单个补丁基元的顶点数glPatchParameteri
:
glPatchParameteri(GL_PATCH_VERTICES, 3);
glDrawArrays(GL_PATCHES, 0, 3);
此外,您还必须通过所有着色器阶段,从顶点着色器到片段着色器一直传递颜色:
Tessellation Control Shader的输入是一个补丁,输出也是补丁。但是输入补丁大小可以与输出补丁大小不同。输入补丁大小由 定义GL_PATCH_VERTICES
,输出补丁大小由 定义layout (vertices = 3) out
。因此,您必须在着色器程序中指定输入补丁的属性如何映射到输出补丁的属性。
#version 450 core
layout (vertices = 3) out;
in VS_OUT
{
vec4 color;
} in_data[];
out VS_OUT
{
vec4 color;
} out_data[];
void main(void)
{
out_data[gl_InvocationID].color = in_data[gl_InvocationID].color;
if (gl_InvocationID = 0)
{
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 5.0;
gl_TessLevelOuter[1] = 5.0;
gl_TessLevelOuter[2] = 5.0;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
Tessellation Evaluation Shader执行插值。细分控制着色器的输出补丁的属性根据 进行插值gl_TessCoord
。
您必须实现在着色器程序中插入属性的算法。
#version 450 core
layout (triangles, equal_spacing, ccw) in;
in VS_OUT
{
vec4 color;
} in_data[];
out VS_OUT
{
vec4 color;
} out_data;
void main(void)
{
out_data.color = in_data[0].color * gl_TessCoord.x + in_data[1].color * gl_TessCoord.y + in_data[2].color * gl_TessCoord.z;
gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position);
}
推荐阅读
- html - div 的转换导致内部 div 行为怪异
- pentaho - 如何在 Pentaho Carte executeJob 中传递参数?
- angular - 在外部单击时禁用 ngx-smart-modal 的关闭
- perl - 如何将输出写入txt文件?
- ios - 我们如何创建可以添加到 Apple Wallet 中的 NFC Pass?
- java - 如何在 jsonb 列上使用 Spring JPA 进行查询?
- javascript - 如何使用鼠标悬停效果更改背景颜色?
- jenkins-pipeline - 从 jenkinsfile 执行 shell 命令
- node.js - 我无法在 debian 上获取 npm
- javascript - 如何在选项卡之间动态路由?