C++ C++;OpenGL不渲染
通过去掉ComputePositionOffsets()和AdjustVertexData()方法,我可以显示一个三角形,但我添加了一些按钮功能来旋转它,以查看屏幕中是否还有其他地方,我不明白为什么它会生成黑屏C++ C++;OpenGL不渲染,c++,opengl,C++,Opengl,通过去掉ComputePositionOffsets()和AdjustVertexData()方法,我可以显示一个三角形,但我添加了一些按钮功能来旋转它,以查看屏幕中是否还有其他地方,我不明白为什么它会生成黑屏 #include <algorithm> #include <string> #include <vector> #include <stdio.h> #include <glload/gl_3_2_comp.h> #inclu
#include <algorithm>
#include <string>
#include <vector>
#include <stdio.h>
#include <glload/gl_3_2_comp.h>
#include <GL/freeglut.h>
#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
double rotate_y = 0;
double rotate_x = 0;
GLuint CreateShader(GLenum eShaderType, const std::string &strShaderFile) {
GLuint shader = glCreateShader(eShaderType);
const char *strFileData = strShaderFile.c_str();
glShaderSource(shader, 1, &strFileData, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
const char *strShaderType = NULL;
switch (eShaderType) {
case GL_VERTEX_SHADER:
strShaderType = "vertex";
break;
case GL_GEOMETRY_SHADER:
strShaderType = "geometry";
break;
case GL_FRAGMENT_SHADER:
strShaderType = "fragment";
break;
}
fprintf(stderr, "Compile failure in %s shader:\n%s\n", strShaderType,strInfoLog);
delete[] strInfoLog;
}
return shader;
}
GLuint CreateProgram(const std::vector<GLuint> &shaderList) {
GLuint program = glCreateProgram();
for (size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
glAttachShader(program, shaderList[iLoop]);
glLinkProgram(program);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
fprintf(stderr, "Linker failure: %s\n", strInfoLog);
delete[] strInfoLog;
}
for (size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
glDetachShader(program, shaderList[iLoop]);
return program;
}
GLuint theProgram;
const std::string strVertexShader("#version 330\n"
"layout(location = 0) in vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n");
const std::string strFragmentShader("#version 330\n"
"out vec4 outputColor;\n"
"void main()\n"
"{\n"
" outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
"}\n");
void InitializeProgram() {
std::vector<GLuint> shaderList;
shaderList.push_back(CreateShader(GL_VERTEX_SHADER, strVertexShader));
shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, strFragmentShader));
theProgram = CreateProgram(shaderList);
std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}
const float vertexPositions2[] = { 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5,
0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5,
-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5,
-0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5,
-0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5 };
GLuint positionBufferObject;
GLuint vao;
void InitializeVertexBuffer() {
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions2), vertexPositions2,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
void init() {
InitializeProgram();
InitializeVertexBuffer();
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
}
void ComputePositionOffsets(float &fXOffset, float &fYOffset) {
const float fLoopDuration = 5.0f;
const float fScale = 3.14159f * 2.0f / fLoopDuration;
float fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
float fCurrTimeThroughLoop = fmodf(fElapsedTime, fLoopDuration);
fXOffset = cosf(fCurrTimeThroughLoop * fScale) * 0.5f;
fYOffset = sinf(fCurrTimeThroughLoop * fScale) * 0.5f;
}
void AdjustVertexData(float fXOffset, float fYOffset) {
std::vector<float> fNewData(ARRAY_COUNT(vertexPositions2));
memcpy(&fNewData[0], vertexPositions2, sizeof(vertexPositions2));
for (int iVertex = 0; iVertex < ARRAY_COUNT(vertexPositions2); iVertex +=
4) {
fNewData[iVertex] += fXOffset;
fNewData[iVertex + 1] += fYOffset;
}
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexPositions2), &fNewData[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//Called to update the display.
//You should call glutSwapBuffers after all of your rendering to display what you rendered.
//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
void display() {
glUseProgram(theProgram);
float fXOffset = 0.0f, fYOffset = 0.0f;
ComputePositionOffsets(fXOffset, fYOffset);
AdjustVertexData(fXOffset, fYOffset);
//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLubyte indices[] = { 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 9, 10, 10, 11,
8, 12, 13, 14, 14, 15, 12, 16, 17, 18, 18, 19, 16, 20, 21, 22, 22,
23, 20 }; // back
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glFlush();
glUseProgram(0);
glutSwapBuffers();
}
//Called whenever the window is resized. The new window size is given, in pixels.
//This is an opportunity to call glViewport or glScissor to keep up with the change in size.
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
}
//Called whenever a key on the keyboard was pressed.
//The key is given by the ''key'' parameter, which is in ASCII.
//It's often a good idea to have the escape key (ASCII value 27) call glutLeaveMainLoop() to
//exit the program.
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 27:
glutLeaveMainLoop();
return;
}
// Right arrow - increase rotation by 5 degree
if (key == GLUT_KEY_RIGHT) rotate_y += 5;
// Left arrow - decrease rotation by 5 degree
else if (key == GLUT_KEY_LEFT) rotate_y -= 5;
else if (key == GLUT_KEY_UP) rotate_x += 5;
else if (key == GLUT_KEY_DOWN) rotate_x -= 5;
// Request display update
glutPostRedisplay();
}
unsigned int defaults(unsigned int displayMode, int &width, int &height) {
return displayMode;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义数组计数(数组)(sizeof(数组)/(sizeof(数组[0])*(sizeof(数组)!=sizeof(void*))| | sizeof(数组[0]))
我猜这是一个组成立方体的3D向量列表,因为代码中有24个索引(6个面*4个角),所有值都是0.5或-0.5。但是,您告诉OpenGL这是一个包含4个组件的向量列表,而不是3个组件:
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
将第二个参数设置为4是很不寻常的。如果将其设置为3,OpenGL将为您将w
组件填充为1。试试看。如果这样做,您将看到一个正方形
除此之外,我在任何地方都看不到透视投影矩阵。如果没有透视投影矩阵,则会得到2D投影,而不是3D投影。事情不会按照您希望的方式显示。您需要在执行旋转和移动之前先将其输入
下面的这些行不会对您的程序产生影响,它们不属于现代图形程序。它们会更改固定函数矩阵堆栈中的矩阵,而您在着色器中不会使用这些矩阵(而且我认为不能,因为您使用的是GLSL 330)。您必须自己将矩阵定义为统一变量
glLoadIdentity();
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);
如果您希望制表符的格式正确,则应使用四个空格替换制表符。请仅发布您遇到问题的代码,并将其组织在单独的代码块中,以便我们可以更轻松地缩小问题。如果您使用GL3,为什么要使用固定函数矩阵堆栈?这不像是在拉modelview ma在某个点进行trix并将其粘贴在制服中。甚至使用(不推荐使用)GLSL内置!我想你只是…希望顶点着色器会以某种方式出现。@genpfault我很不幸地试图将一本旧书与现代示例混合在一起。如果你的书太旧了,仍然使用固定的函数,这是行不通的。自那以后,一切都发生了变化。遗憾的是,让你的第一个三角形出现在屏幕上要复杂得多在现代OpenGL中是很难的,这使得它比以前更难学习。但是它的灵活性是值得的。你了解这段代码中有多少内容?
glLoadIdentity();
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);