【问题标题】:opengl 2.1 and texturesopengl 2.1 和纹理
【发布时间】:2017-02-13 02:43:02
【问题描述】:

我正在尝试使用 opengl 2.1 和 glsl 120 显示纹理(是的,它是一个锅),但我不知道该怎么做,我只能得到一个黑色四边形,我一直遵循本教程:A Textured CubeOpenGl - Textures,我的理解是我需要:

  1. 指定要附加到每个顶点的纹理坐标(在我的例子中是 6 个顶点,一个没有索引的立方体)
  2. 加载纹理并将其绑定到纹理单元中(默认为0)
  3. 调用 glDrawArrays

  4. 在着色器中我需要:

  5. 在顶点着色器的属性中接收纹理坐标,并通过可变变量将其传递给片段着色器
  6. 在片段着色器中,使用采样器对象在可变变量指定的位置从纹理中采样像素。

一切都正确吗?

这是我如何创建纹理 VBO 并加载纹理:

void Application::onStart(){
unsigned int format;
SDL_Surface* img;

float quadCoords[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.5f, 0.5f, 0.0f,
        0.5f, 0.5f, 0.0f,
        -0.5f, 0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f};

const float texCoords[] = {
        0.0f, 0.0f, 
        1.0f, 0.0f, 
        1.0f, 1.0f, 
        1.0f, 1.0f, 
        0.0f, 1.0f,
        0.0f, 0.0f};

//shader loading omitted ...
sprogram.bind(); // call glUseProgram(programId)
//set the sampler value to 0 -> use texture unit 0
sprogram.loadValue(sprogram.getUniformLocation(SAMPLER), 0);

//quad
glGenBuffers(1, &quadBuffer);
glBindBuffer(GL_ARRAY_BUFFER, quadBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*18, quadCoords, GL_STATIC_DRAW);
//texture
glGenBuffers(1, &textureBuffer);
glBindBuffer(GL_ARRAY_BUFFER, textureBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*12, texCoords, GL_STATIC_DRAW);

//load texture
img = IMG_Load("resources/images/crate.jpg");

if(img == nullptr)
    throw std::runtime_error(SDL_GetError());

glGenTextures(1, &this->texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->w, img->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img->pixels);

SDL_FreeSurface(img);
}

渲染阶段:

glClear(GL_COLOR_BUFFER_BIT);

glEnableVertexAttribArray(COORDS);
glBindBuffer(GL_ARRAY_BUFFER, quadBuffer);
glVertexAttribPointer(COORDS, 3, GL_FLOAT, GL_FALSE, 0, nullptr);

glEnableVertexAttribArray(TEX_COORDS);
glBindBuffer(GL_ARRAY_BUFFER, textureBuffer);
glVertexAttribPointer(TEX_COORDS, 2, GL_FLOAT, GL_FALSE, 0, nullptr);

//draw the vertices
glDrawArrays(GL_TRIANGLES, 0, 6);

顶点着色器:

#version 120

attribute vec3 coord;
attribute vec2 texCoord;

varying vec2 UV;

void main(){    
    gl_Position = vec4(coord.x, coord.y, coord.z, 1.0);
    UV = texCoord;
}

片段着色器:

#version 120

uniform sampler2D tex;
varying vec2 UV;

void main(){
    gl_FragColor.rgb = texture2D(tex, UV).rgb;
    gl_FragColor.a = 1.0;
}

我知道教程使用 out 而不是 varying 所以我尝试“转换”代码,还有这个教程:Simple Texture - LightHouse 解释了 gl_MultiTexCoord0 属性和 gl_TexCoord 数组内置,但这几乎是我正在做的事情。我想知道是否做得很好,如果没有,我想知道如何使用 opengl 2.1 和 glsl 120 在屏幕上显示简单的 2d 纹理

【问题讨论】:

  • 将纹理绑定到采样器的部分在哪里?
  • @immibis,在绑定我的纹理之前,我调用glActiveTexture(GL_TEXTURE0) 这是着色器中的默认采样器
  • 不确定这是否是您的全部代码,但您似乎没有设置纹理过滤器。默认缩小过滤器带有 mipmap,并且您的纹理不是 mipmap 完整的(因此采样不起作用)。
  • @dehass,就是这样,我添加了glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);,它现在正在工作,我真的想做一个极简纹理渲染器测试,我决定使用这个函数调用离开。感谢您的解决方案

标签: c++ opengl


【解决方案1】:

您是否有特殊的理由将 opengl 2.1 与 glsl 版本 1.2 一起使用?如果不坚持使用openGl 3.0,因为它更容易理解恕我直言。 我猜你有两个大问题:

首先得到一个黑色四边形:如果它的大小占据了你的洞应用程序,那么它的背景颜色。这意味着它根本不绘制任何东西。 我认为(通过测试)OpenGL有一个默认程序,即使你已经在gpu上设置了一个顶点数组/缓冲区对象,它也会被激活。它应该在你的窗口中呈现为一个白色的四边形......所以这可能是你的第一个问题。我不知道 opengl 2.1 是否有顶点缓冲区数组,但 opengl 3.0 有,你应该明确地使用它!

第二:你不在渲染阶段使用你的着色器程序; 在绘制四边形之前调用此函数:

glUseProgram(myProgram); // The myProgram variable is your compiled shader program

如果您希望我解释如何使用 OpegGL 3.0 ++ 绘制四边形,请告诉我 :) ...这与您已经在代码中编写的内容相距不远。

【讨论】:

  • 是的,我有理由使用 ogl 2.1 和 glsl 1.2,我的电脑很旧(从 2010 年开始),我现在真的不能买新的,四边形绘制正确,它不会占据整个屏幕,我也用三角形进行了测试。我真的很抱歉,但我忘了显示我绑定我的 gl 程序的位置,因为我的 gl 包装类我省略了 //... shader loading 部分,我现在就改变它。
  • 这里是一些有用的网站,按版本显示 ogl 中可用的所有功能:docs.gl/gl2/glUseProgram
  • 如果您的四边形绘制到屏幕上,那么您的纹理 UV 可能无法到达着色器。还有另一种方法: vbo = { v1.x, v1.y, v1.z, uv1.x , uv1.y, v2.x, v2.y, v2.z, uv2.x , uv2.y, /*依此类推*/ } 基本上顶点和 uv 数据被打包在同一个 vbo 中,当调用 glVertexAttribPointer(COORDS, 3, GL_FLOAT, GL_FALSE, 0, nullptr);将 0(步幅)更改为 3* sizeof(GLfloat) glVertexAttribPointer(TEX_COORDS, 2, GL_FLOAT, GL_FALSE, 0, nullptr);这里 0 到 2 * sizeof(GLfloat) // stride and nullptr to (GLvoid*)(3*sizeof(GLfloat)) //(偏移量)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-19
  • 1970-01-01
相关资源
最近更新 更多