我是OpenGL的新手,我在Shaders https://learnopengl.com/Getting-started/Textures上关注本教程。 我无法工作,因为屏幕最终只是全黑。该代码使用glew和glut而不是本教程中的glfw。
这是怎么回事?
glEnable(GL_TEXTURE_2D);
GL_TEXTURE0
,以便下次调用glBindTexture(GL_TEXTURE_2D, texture)
引用到此纹理单元。stbi_load
函数加载纹理glTexImage2D
加载纹理,该纹理具有预先作为指针传递给width
的参数(height
,texture_data
,stbi_load
),以便加载它们。ourShader
),附加顶点着色器和片段着色器。链接“ ourShader”程序,然后再次打印错误(没有显示)。注意事项:
gluPerspective
进行投影,在剪切平面0.1附近并且远1000(由于它向下看-z,因此不应剪切对象,我也像glTranslatef(0, 0, -10)
那样翻译对象)这是myDisplay回调:
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* vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec3 aPos;\n"
"layout(location = 1) in vec3 aColor;\n"
"layout(location = 2) in vec2 aTexCoord;\n"
"out vec3 ourColor;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos, 1.0);\n"
"ourColor = aColor;\n"
"TexCoord = aTexCoord;\n"
"}\n";
片段着色器
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";
更新日志-已解决
投影,视图和模型转换进入着色器内部,使用
glm::projection
glm::lookat
在渲染之前启用属性(颜色,纹理)
glutInitContextVersion(3, 3);
glutInitContextProfile(GLUT_CORE_PROFILE);
最终代码在这里:[https://pastebin.com/D8DgPqaT]
迷幻着色器:[https://pastebin.com/vtJ3Cr6i]
答案 0 :(得分:2)
glEnable(GL_TEXTURE_2D)
,因为在(片段)着色器中可以使用纹理,也可以不使用纹理。
着色器代码定义是否应用纹理。 glEnable(GL_TEXTURE_2D)
用于不推荐使用的Fixed Function Pipeline,仅不使用着色器。
使用固定功能矩阵堆栈(glMatrixMode
,glLoadIdentity
,gluPerspective
,...)也是没有用的。您必须使用Uniform变量(类型为mat4
)。
此函数更改固定函数矩阵堆栈上的矩阵。此矩阵适用于由glVertex
或glVertexPointer
设置的固定函数顶点坐标,但前提是没有着色器代码。
如果有着色器,则必须自己进行矩阵转换。
在GLSL中,存在诸如gl_ModelViewMatrix
,gl_ProjectionMatrix
或gl_ModelViewProjectionMatrix
之类的内置制服,使您可以访问固定函数矩阵堆栈上的矩阵。但是,这种制服也已被弃用,并且在GLSL #version 330 core
中不再可用。
编写具有两个统一mat4 u_proj
和mat4 u_view
的着色器。通过着色器代码变换顶点坐标。
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
uniform mat4 u_proj;
uniform mat4 u_view;
void main()
{
gl_Position = u_proj * u_view * vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = aTexCoord;
}
获取程序链接后的统一位置:
GLint proj_loc = glGetUniformLocation(ourShader, "u_proj");
GLint view_loc = glGetUniformLocation(ourShader, "u_view");
计算投影矩阵和视图矩阵。我建议使用OpenGL Mathematics (GLM)库,该库旨在进行基于OpenGL和GLSL的相关计算,并且基于OpenGL Shading Language (GLSL)。另请参见glm::perspective
和glm::lookAt
:
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
glm::mat4 proj = glm::perspective(glm::radians(fov_degrees)), aspect, near, far);
glm::mat4 view = glm::lookAt(eye, target, up);
通过glUseProgram
安装程序(glUniformMatrix4fv
)后设置制服:
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(proj));
glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(view));
审查代码[https://pastebin.com/KWDxcEen]和着色器[https://pastebin.com/yq3rQEga]
如果着色器已成功编译,则必须由glGetShaderiv
检查
glGetShaderiv(shader_ID, GL_COMPILE_STATUS, &status);
比较以检查程序是否已成功链接,必须由glGetProgramiv
glGetProgramiv(program_ID, GL_LINK_STATUS, success_f);
数组纹理坐标由大小为2(u,v)的元组组成:
glVertexAttribPointer(2,
2, // <---- 2 instead of 3
GL_FLOAT,
GL_FALSE,
8 * sizeof(GLfloat),
(void*)(6 * sizeof(GLfloat))
);
glDrawArrays
的第三个参数是顶点的数量,而不是基元的数量:
glDrawArrays(GL_TRIANGLES, 0, 6); // <---- 6 instead of 2
loadTexture
的第二个参数必须是输出参数。它必须是参考(unsigned char *& buff
):
bool loadTexture(
const std::string &filename,
unsigned char*& buff, // < ---- unsigned char*&
int* w, int* h, int* nc);
将顶点属性启用或禁用的状态存储在Vertex Array Object中。在显示功能中无需再次执行此操作:
void myDisplay(void)
{
// ....
glBindVertexArray(VAO);
// unecessary:
//glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
//glEnableVertexAttribArray(2);
最后,我建议添加[[glutPostRedisplay()
]
(https://www.opengl.org/resources/libraries/glut/spec3/node20.html)调用显示功能(myDisplay
),以连续更新场景。