我正在尝试纹理VBO / VAO模型立方体。立方体肯定是正确渲染/绘制的,据我所知,我正在做加载纹理所需的一切。
然而,当应用纹理时,它似乎取纹理中所有颜色的平均值,然后将该平均值应用于整个立方体。这导致它看起来像是“涂有”普通的常规颜色,如下面的屏幕截图所示:
这是纹理;
我不知道为什么会这样。下面是我的init,loadTexture和显示函数的代码(我没有编写loadTexture函数):
初始化功能 (仅显示与立方体+纹理相关的代码) void init(void){ 。 。 。 pyramidTexture = TextureLoader :: fiLoadTexture(wstring(L“Common \ Resources \ Textures \ Sandstone.png”));
// Setup VAO for pyramid object
glGenVertexArrays(1, &pyramidVAO);
glBindVertexArray(pyramidVAO);
// Setup VBO for vertex position data
glGenBuffers(1, &pyramidVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, pyramidVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidVertices), pyramidVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0); // attribute 0 gets data from bound VBO (so assign vertex position buffer to attribute 0)
// Setup VBO for vertex colour data
glGenBuffers(1, &pyramidColourBuffer);
glBindBuffer(GL_ARRAY_BUFFER, pyramidColourBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidColours), pyramidColours, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, 0, (const GLvoid*)0); // attribute 1 gets colour data
glGenBuffers(3, &pyramidTexCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, pyramidTexCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidTexCoordArray), pyramidTexCoordArray, GL_STATIC_DRAW);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
// Enable vertex position and colour + Texture attribute arrays
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(3);
// Setup VBO for face index array
glGenBuffers(1, &pyramidIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pyramidIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pyramidVertexIndices), pyramidVertexIndices, GL_STATIC_DRAW);
glBindVertexArray(0);
glEnable(GL_NORMALIZE); // If we scale objects, ensure normal vectors are re-normalised to length 1.0 to keep lighting calculations correct (see lecture notes)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Best colour interpolation results
.
.
.
}
LoadTexture功能
GLuint TextureLoader::fiLoadTexture(const wstring& textureFilePath) {
BOOL fiOkay = FALSE;
GLuint newTexture = 0;
fipImage I;
// Convert wstring to const char*
wstring_convert<codecvt_utf8<wchar_t>, wchar_t> stringConverter;
string S = stringConverter.to_bytes(textureFilePath);
const char *filename = S.c_str();
// Call FreeImage to load the image file
fiOkay = I.load(filename);
if (!fiOkay) {
cout << "FreeImagePlus: Cannot open image file.\n";
return 0;
}
fiOkay = I.flipVertical();
fiOkay = I.convertTo24Bits();
if (!fiOkay) {
cout << "FreeImagePlus: Conversion to 24 bits successful.\n";
return 0;
}
auto w = I.getWidth();
auto h = I.getHeight();
BYTE *buffer = I.accessPixels();
if (!buffer) {
cout << "FreeImagePlus: Cannot access bitmap data.\n";
return 0;
}
glGenTextures(1, &newTexture);
glBindTexture(GL_TEXTURE_2D, newTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, buffer);
// Setup default texture properties
if (newTexture) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
return newTexture;
}
显示功能
void display(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set viewport to the client area of the current window
glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
// Get view-projection transform as a GUMatrix4
GUMatrix4 T = mainCamera->projectionTransform() * mainCamera->viewTransform();
if (principleAxes)
principleAxes->render(T);
if (texturedQuad)
texturedQuad->render(T * GUMatrix4::translationMatrix(0.5f, 0.5f, 0.0f));
// Fixed function rendering (Compatability profile only) - use this since CGImport is written against OpenGL 2.1
glUseProgram(0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMultMatrixf((const float*)mainCamera->projectionTransform().M);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMultMatrixf((const float*)mainCamera->viewTransform().M);
glMultMatrixf((const float*)GUMatrix4::translationMatrix(0.0f, -0.15f, 0.0f).M);
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT, GL_FILL);
if (exampleModel)
exampleModel->renderTexturedModel();
glDisable(GL_TEXTURE_2D);
//Define position and direction (so appear at fixed point in scene)
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
// enable texturing
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//
// Pyramid VBO rendering
//
// Use basic shader for rendering pyramid (we'll look at this in more detail next week)
glUseProgram(basicShader);
static GLint mvpLocationPyramid = glGetUniformLocation(basicShader, "mvpMatrix");
glUniformMatrix4fv(mvpLocationPyramid, 1, GL_FALSE, (const GLfloat*)&(T.M));
GUMatrix4 pyramidModelTransform = GUMatrix4::translationMatrix(-5.75f, 0.0f, 0.0f) * GUMatrix4::scaleMatrix(2.0f, 2.0f, 2.0f);
GUMatrix4 mvpPyramid = T * pyramidModelTransform;
glUniformMatrix4fv(mvpLocationPyramid, 1, GL_FALSE, (const GLfloat*)&(mvpPyramid.M));
// Bind VAO that contains all relevant pyramid VBO buffer and attribute pointer bindings
glBindVertexArray(pyramidVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, pyramidTexture);
// Draw pyramid
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (const GLvoid*)0);
// Unbind pyramid VAO (or bind another VAO)
glBindVertexArray(0);
glutSwapBuffers();
}
我一直试图解决这个问题几个小时没有任何运气,因此任何支持都会受到大力赞赏!!!
编辑:在VAO属性+着色器中添加
VAO设置
// Per-vertex position vectors
static float pyramidVertices[32] =
{
//Front
0.0f, 0.0f, 0.0f, 1.0f, //BtmLeft
1.0f, 0.0f, 0.0f, 1.0f, //BtmRight
1.0f, 1.0f, 0.0f, 1.0f, //TopRight
0.0f, 1.0f, 0.0f, 1.0f, //TopLeft
//Back
0.0f, 1.0f, 1.0f, 1.0f, //TopLeft
1.0f, 1.0f, 1.0f, 1.0f, //TopRight
1.0f, 0.0f, 1.0f, 1.0f, //BottomRight
0.0f, 0.0f, 1.0f, 1.0f //BottomLeft
};
// Per-vertex colours (RGBA) floating point values
static float pyramidColours[32] =
{
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f
};
// 5 faces each with 3 vertices (each face forms a triangle)
static unsigned short pyramidVertexIndices[36] =
{
//Front
0, 3, 2,
2, 1, 0,
//Right
4, 3, 0,
0, 7, 4,
//Back
4, 7, 6,
6, 5, 4,
//Top
4, 5, 3,
3, 5, 2,
//Left
2, 5, 1,
1, 5, 6,
//Bottom
6, 7, 0,
0, 1, 6
};
static unsigned short pyramidTexCoordArray[24] =
{
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f
};
顶点着色器
#version 330
uniform mat4 mvpMatrix;
layout (location=0) in vec4 vertexPos;
layout (location=3) in vec2 vertexTexCoord;
out vec2 texCoord;
void main(void) {
mat4 M;
M[0] = vec4(1.0);
ivec2 a = ivec2(1, 2);
//vec3 b = vec3(2.0, 4.0, 1.0) + a;
texCoord = vertexTexCoord;
gl_Position = mvpMatrix * vertexPos;
}
片段着色器
#version 330
uniform sampler2D texture;
in vec2 texCoord;
layout (location=0) out vec4 fragColour;
void main(void) {
vec4 texColor = texture2D(texture, texCoord);
fragColour = texColor;
}
答案 0 :(得分:2)
您将数据定义为unsigned short
:
static unsigned short pyramidTexCoordArray[24]
但必须是float
。
答案 1 :(得分:1)
有很多奇怪的事情:
您正在为纹理坐标生成3个VBO,但只使用一个。除非pyramidTexCoordBuffer的类型为GLuint [3](我认为它不是由于&amp;),否则你写的是超出界限。
编辑:这是指glGenBuffers(3, &pyramidTexCoordBuffer);
行,它分配3个缓冲区并将它们存储在从GLuint
开始的三个连续pyramidTexCoordBuffer
个变量中。由于pyramidTexCoordBuffer
很可能是GLuint
,pyramidTexCoordBuffer[1]
和pyramidTexCoordBuffer[2]
是指未分配的内存。
pyramidTexCoordArray
数组指定为unsigned short
,但您正在为它编写浮点数。由于它是无符号的,至少负数将消失。
此外,您使用
告诉OpenGLglVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
表示数据的类型为GL_FLOAT
(它不是),并且每个顶点有两个浮点数(但数据每个顶点有3个元素):