我画了一个盒子。我添加了处理vao和vbo的基本类。
class BasicObject_V2
{
public:
BasicObject_V2(GLuint typeOfPrimitives = 0){
this->typeOfPrimitives = typeOfPrimitives;
switch (this->typeOfPrimitives){
case GL_QUADS: numVertsPerPrimitive = 4; break;
}}
void allocateMemory(){
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertexAttributes), &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 48, (const void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 48, (const void*)12);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 48, (const void*)24);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 48, (const void*)40);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
}
GLuint vboID;
GLuint vaoID;
GLuint typeOfPrimitives;
GLuint numVertsPerPrimitive;
int getNumberOfVertices(){
return vertices.size();
}
struct vertexAttributes{
glm::vec3 pos;
glm::vec3 normal;
glm::vec4 color;
glm::vec2 texCoord;
};
std::vector<vertexAttributes> vertices;
};
这是我的Box-class。
class Box_V2 : public BasicObject_V2 {
public:
Box_V2(float width = 1, float height = 1, float length = 1) : BasicObject_V2(GL_QUADS) {
float wHalf = width / 2.0f;
float hHalf = height / 2.0f;
float lHalf = length / 2.0f;
vertexAttributes va;
glm::vec3 corners[8];
corners[0] = glm::vec3(-wHalf, -hHalf, lHalf);
corners[1] = (...)
glm::vec3 normals[6];
normals[0] = glm::vec3(0, 0, 1); // front
//(...)
// FRONT
va.pos = corners[0];
va.normal = normals[0];
va.texCoord = glm::vec2(0.0, 0.0);
vertices.push_back(va);
//...
allocateMemory();
}
};
我也为它设置了纹理(根据opengl的可行例子),但它确实起作用。
static GLubyte checkImage[128][128][4];
void makeCheckImage(void)
{
int i, j, c;
for (i = 0; i<128; i++) {
for (j = 0; j<128; j++) {
c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0)) * 255;
checkImage[i][j][0] = (GLubyte)c;
checkImage[i][j][1] = (GLubyte)c;
checkImage[i][j][2] = (GLubyte)c;
checkImage[i][j][3] = (GLubyte)255;
}}}
void init(){
glClearColor(0.7, 0.4, 0.6, 1);
//Create a Texture
makeCheckImage();
//Texure
glGenTextures(4, tex);
//glCreateTextures(GL_TEXTURE_2D, 4, tex);//4.5
glTextureStorage2D(tex[0], 0, GL_RGBA32F, 2, 2);
glBindTexture(GL_TEXTURE_2D, tex[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGBA, GL_FLOAT, checkImage);
//glTextureSubImage2D(tex[0], 0, 0, 0, 2, 2, GL_RGBA, GL_FLOAT, checkImage);//4.5
//load the shader
programID = loadShaders("vertex.vsh", "fragment.fsh");
glUseProgram(programID);
//create a box
box_v2 = new Box_V2();
glBindTexture(GL_TEXTURE_2D, tex[0]);
}}
void drawing(BasicObject* object){
glBindVertexArray(object->vaoID);
glDrawArrays(object->typeOfPrimitives, 0, object->getNumberOfVertices() * object->numVertsPerPrimitive);
glBindVertexArray(0);
}
这是我的着色器: VS:
#version 450 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec4 color;
layout(location = 3) in vec2 texCoord;
uniform mat4 rotate;(...)
out vec4 v_normal;
out vec4 v_color;
out vec4 v_pos;
out vec2 v_texCoord;
void main(){
v_normal = rotate*vec4(normal,1);//*model;
v_color=color;
v_texCoord=texCoord;
gl_Position = rotate*scale*trans*vec4(pos.xyz, 1);
}
和FS:
#version 450 core
in vec4 v_color;
in vec2 v_texCoord;
uniform sampler2D ourTexture;
out vec4 outColor;
void main(){
//outColor=texelFetch(ourTexture, ivec2(gl_FragCoord.xy), 0); //4.5
outColor=texture(ourTexture,v_texCoord*vec2(3.0, 1.0));
}
现在它绘制一个没有任何纹理的黑盒子。我是OpenGL的新手,我找不到问题所在。
答案 0 :(得分:3)
您的代码存在很多问题。看起来你试图用一种方式写它,然后尝试用另一种方式写它,导致某种类型的弗兰肯斯坦代码,它不是真的这样或那样。
glGenTextures(4, tex);
//glCreateTextures(GL_TEXTURE_2D, 4, tex);//4.5
glTextureStorage2D(tex[0], 0, GL_RGBA32F, 2, 2);
这是一个很好的例子。您使用非DSA glGenTextures
来电,但是您立即转身并使用DSA glTextureStorage2D
来电。你不能那样做。为什么?因为tex[0]
尚未创建。
glGenTextures
仅为纹理分配名称,而不是其状态数据。只有通过绑定纹理才能获得内容。这就是DSA引入glCreate*
功能的原因;他们为对象分配名称和状态。这也是glCreateTextures
占据目标的原因;该目标是纹理对象状态的一部分。
简而言之,注释掉的电话一直都是正确的。查看您编写的代码,glTextureStorage2D
调用失败并出现OpenGL错误(仅供参考:打开KHR_debug以查看错误发生的时间)。
因此,让我们看一下如果我们拿出失败部分你的代码会是什么样子:
glGenTextures(4, tex);
glBindTexture(GL_TEXTURE_2D, tex[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGBA, GL_FLOAT, checkImage);
这里有两个问题。首先,正如BDL所提到的,您的数据描述不正确。您已经通过了GLubyte
,但是您告诉OpenGL您正在通过GLfloat
。不要骗OpenGL。
其次,internal format。因为您使用了未经过大小写的内部格式(并且因为您不在OpenGL ES中),所以您的实现选择的格式将是 unsigned normalized 。它不会是一个32位浮点格式。如果您需要其中一个,则必须明确要求GL_RGBA32F
。
此外,由于您为纹理分配了可变存储(即:因为glTextureStorage2D
失败),您现在遇到了问题。您只分配了一个mipmap级别,但默认过滤模式将尝试从多个mipmap中获取。并且您从未将纹理mipmap range设置为仅从第一个采样。所以你的纹理不完整。不可变的存储纹理会使mipmap范围与您分配的内容相匹配,但可变的存储纹理并不是那么好。
在创建可变存储纹理时,总是设置mipmap范围:
glTexParameteri(GL_TEXTURE2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE2D, GL_TEXTURE_MAX_LEVEL, 0); //It's a closed range.
最后,将纹理绑定到单元0进行渲染(主要是偶然的,因为你从不调用glActiveTexture
)。但是,通过将ourTexture
统一值设置为0,您永远不会费心通知您的着色器。
答案 1 :(得分:0)
您的代码存在以下几个问题:
数据类型与数据不匹配
数据采用无符号字节格式(GLubyte checkImage[128][128][4]
),每像素大小为4字节(每个通道1个字节),但是告诉OpenGL它是GL_FLOAT
格式的,每个像素需要16个字节(每个通道4个字节)。
数据存储
见246Nt。
的回答<强>的mipmap /过滤器强>
默认情况下,OpenGL将缩小过滤器设置为GL_LINEAR_MIPMAP_LINEAR
,该过滤器要求用户为纹理提供有效的mipmap。可以将此过滤器更改为GL_LINEAR
或GL_NEAREST
,不需要mipmap(请参阅glTexParameteri
),也可以生成mipmap(glGenerateMipmaps
)。