C++ OpenGL着色器问题(不显示任何内容)
我是OpenGL的新手,我一直在学习关于着色器的教程。 我的电脑无法正常工作,因为屏幕最终完全变黑了。这段代码使用glew和glut,而不是像教程中那样使用glfw 发生了什么事C++ OpenGL着色器问题(不显示任何内容),c++,opengl,glsl,shader,C++,Opengl,Glsl,Shader,我是OpenGL的新手,我一直在学习关于着色器的教程。 我的电脑无法正常工作,因为屏幕最终完全变黑了。这段代码使用glew和glut,而不是像教程中那样使用glfw 发生了什么事 我有一个顶点列表,然后存储在VBO中,它的属性由VAO绑定 按3个顶点+3种颜色+2个纹理坐标的顺序设置顶点属性 glEnable(GL_纹理_2D) 确保激活GL_TEXTURE0以便下次调用 glBindTexture(GL\u TEXTURE\u 2D,纹理)被引用到此纹理单元 我使用stbi\u load函数
- 我有一个顶点列表,然后存储在VBO中,它的属性由VAO绑定
- 按3个顶点+3种颜色+2个纹理坐标的顺序设置顶点属性
glEnable(GL_纹理_2D)代码>
- 确保激活
以便下次调用GL_TEXTURE0
被引用到此纹理单元glBindTexture(GL\u TEXTURE\u 2D,纹理)
- 我使用
函数加载纹理stbi\u load
- 加载带有参数(
,宽度
,高度
)的纹理数据
纹理,这些参数作为指针预先传递给glTexImage2D
),以便加载它们stbi\u加载
- 创建顶点着色器,附加源(在VertexShaders.h中),编译着色器,打印着色器错误(无显示)
- 创建片段着色器,附加源(在FragmentShaders.h中),编译着色器,打印着色器错误(无显示)
- 创建着色器程序(
),附加顶点着色器和片段着色器。链接“ourShader”程序,再次打印错误(无显示)ourShader
- 投影是用
进行的,接近剪裁平面0.1,远1000(因为它向下看-z,所以不应该剪裁对象,我也像这样翻译对象glutransprospective
)glTranslatef(0,0,-10)
- 正在加载纹理(文件存在,加载时会生成字节数据,至于纹理图像,它就是这个(512x512)
void myDisplay(void)
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -10);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glUseProgram(ourShader);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glutSwapBuffers();
}
主设置
int main(){
//glut initialization stuff...left this out
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
float texCoords[] = {
0.0f, 0.0f, // lower-left corner
1.0f, 0.0f, // lower-right corner
0.5f, 1.0f // top-center corner
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
//frameBuffer
glGenBuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR: Framebuffer not bound" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glDeleteFramebuffers(1, &fbo);
//VAO
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Vertex Attributes
glEnableVertexAttribArray(0); //pozicija
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(0));
glEnableVertexAttribArray(1); //boja
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2); //boja
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
std::string path = "C:\\Projects\\Myproj\\container.jpg";
bool success = loadTexture(path,texture_data,&tex_width, &tex_height, &nchannels);
if (success)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "ERROR::STBI::FAILED TO LOAD TEXTURE" << std::endl;
}
stbi_image_free(texture_data);
int success_f;
char infoLog[512];
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
getShaderStatus(vertexShader, &success_f, infoLog);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
getShaderStatus(fragmentShader, &success_f, infoLog);
ourShader = glCreateProgram();
glAttachShader(ourShader, vertexShader);
glAttachShader(ourShader, fragmentShader);
glLinkProgram(ourShader);
getShaderStatus(ourShader, &success_f, infoLog);
glUseProgram(ourShader);
glUniform1i(glGetUniformLocation(ourShader, "ourTexture"), 0);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glutMainLoop();
}
片段着色器
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 ourColor;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
"FragColor = texture(ourTexture, TexCoord);\n"
"}\n";
更新日志-已解决
- 实现着色器时不需要glEnable(GL_纹理_2D)
- 投影、视图和模型变换进入着色器内部,使用
glm::投影 glm::注视
- 渲染前启用属性(颜色、纹理)
- 对OpenGL API的Freeglut支持(>=3.2)
glutInitContextVersion(3,3);
glutInitContextProfile(GLUT_CORE_PROFILE);
最终代码如下:[]
迷幻着色器:[]
在使用着色器时是不必要的,因为纹理是否使用是在(片段)着色器中实现的。着色器代码定义是否应用纹理。
glEnable(GL\u texture\u 2D)
仅用于不推荐使用的材质,不带着色器
此外,使用固定函数矩阵堆栈(glMatrixMode
,glLoadIdentity
,glupspective
,…)也是无用的。必须使用变量(类型为mat4
)。
此函数更改固定函数矩阵堆栈上的矩阵。此矩阵应用于由或设置的固定函数顶点坐标,但仅当没有着色器代码时。如果有着色器,则必须自己进行矩阵变换。
在GLSL中存在内置的一致性,如
gl_ModelViewMatrix
、gl_ProjectionMatrix
或gl_ModelViewProjectionMatrix
,它们允许您访问固定函数矩阵堆栈上的矩阵。但是这种一致性也被弃用,在GLSL版本330 core
中不再可用
编写一个具有2个mat4 u_proj
和mat4 u_view
的着色器。通过着色器代码变换顶点坐标
#版本330核心
vec3 aPos中的布局(位置=0);
vec3颜色中的布局(位置=1);
vec2 aTexCoord中的布局(位置=2);
外显颜色;
out vec2 TexCoord;
统一材料工程;
统一的mat4 u_视图;
void main()
{
gl_位置=u_项目*u_视图*vec4(aPos,1.0);
我们的颜色=颜色;
TexCoord=aTexCoord;
}
链接程序后获取统一的位置:
GLint proj_loc = glGetUniformLocation(ourShader, "u_proj");
GLint view_loc = glGetUniformLocation(ourShader, "u_view");
计算投影矩阵和视图矩阵。我建议使用库,该库设计用于进行OpenGL和GLSL相关计算,并基于。另请参见和:
#包括
#包括
#包括
安装程序()后,通过以下方式设置制服:
glUniformMatrix4fv(proj_loc,1,GL_FALSE,glm::value_ptr(proj));
glUniformMatrix4fv(视图位置,1,GL错误,glm::值ptr(视图));
查看代码[和着色器][ 如果着色器已成功编译,则必须由 与检查程序是否已成功链接相比,必须由 数组纹理坐标由大小为2(u,v)的元组组成:
loadTexture
的第二个参数必须是一个输出参数。它必须是一个引用(unsigned char*&buff
):
最后,我建议添加一个[glutPostRedisplay()
]
()调用显示函数(
myDisplay
),以持续更新场景。没有深入研究您的代码,但我搜索了您的函数myDisplay,它似乎已定义,但没有使用。这可能已经是问题所在,否则您应该在使用它的位置显示代码。glEnable(GL_TEXTURE_2D)
已被弃用,在使用着色器时没有意义。此外,使用固定函数矩阵堆栈(glMatrixMode
,glLoadIdentity
,…)也是无用的。您必须使用(类型mat4
)@MichaelMahn这是一个回调函数,在调用glutMainLoop()时会调用它,但我在离开的glut设置中添加了回调out@Rabbid76你能解释一下为什么它没有意义吗?另外,我应该叫glBindTexture(GL_TEXTURE_2D,TEXTURE);在用glTexImage2D加载纹理之前?非常感谢你的回答,我会尝试实现你的建议。现在我有另一个问题
GLint proj_loc = glGetUniformLocation(ourShader, "u_proj");
GLint view_loc = glGetUniformLocation(ourShader, "u_view");
glm::mat4 proj = glm::perspective(glm::radians(fov_degrees)), aspect, near, far);
glm::mat4 view = glm::lookAt(eye, target, up);
glGetShaderiv(shader_ID, GL_COMPILE_STATUS, &status);
glGetProgramiv(program_ID, GL_LINK_STATUS, success_f);
glVertexAttribPointer(2,
2, // <---- 2 instead of 3
GL_FLOAT,
GL_FALSE,
8 * sizeof(GLfloat),
(void*)(6 * sizeof(GLfloat))
);
glDrawArrays(GL_TRIANGLES, 0, 6); // <---- 6 instead of 2
bool loadTexture(
const std::string &filename,
unsigned char*& buff, // < ---- unsigned char*&
int* w, int* h, int* nc);
void myDisplay(void)
{
// ....
glBindVertexArray(VAO);
// unecessary:
//glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
//glEnableVertexAttribArray(2);