gpt4 book ai didi

c++ - 如何使用 OpenGL 和 C++ 加载多个纹理?

转载 作者:行者123 更新时间:2023-11-28 01:29:59 26 4
gpt4 key购买 nike

继我之前的问题 here为了使用 OpenGL 和 Obj-C 交换图像,我决定也使用 original tutorial使用带有着色器和纹理的 C++。我想做的是切换不同的纹理。这是我的[UPDATED]代码

#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "SOIL2/SOIL2.h"
#include "Shader.h"

using namespace std;

//window
const GLuint WIDTH = 750, HEIGHT = 750;
int main( )
{
glfwInit( );

//GLFW
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE ); //only for mac
glfwWindowHint( GLFW_RESIZABLE, GL_FALSE );

GLFWwindow *window = glfwCreateWindow( WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr );

int screenWidth, screenHeight;
glfwGetFramebufferSize( window, &screenWidth, &screenHeight );

if ( nullptr == window )
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate( );
return EXIT_FAILURE;
}

glfwMakeContextCurrent( window );

//ModernOpenGL
glewExperimental = GL_TRUE;

if ( GLEW_OK != glewInit( ) )
{
cout << "Failed to initialize GLEW" << endl;
return EXIT_FAILURE;
}

//viewport
glViewport( 0, 0, screenWidth, screenHeight );

//enable alpha
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

//shaders
Shader ourShader( "resources/shaders/core.vs", "resources/shaders/core.frag" );

//vertices
GLfloat vertices[] =
{
//position //color //texture Coords
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Top Right
1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Left
-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // Top Left
};

GLuint indices[] =
{
0, 1, 3, // 1st triangle
1, 2, 3 // 2nd triangle
};

GLuint VBO, VAO, EBO;
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 );

//position
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof( GLfloat ), ( GLvoid * ) 0 );
glEnableVertexAttribArray(0);

//color
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof( GLfloat ), ( GLvoid * )( 3 * sizeof( GLfloat )));
glEnableVertexAttribArray(1);

//texture Coord
glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof( GLfloat ), ( GLvoid * )( 6 * sizeof( GLfloat )));
glEnableVertexAttribArray( 2 );

glBindVertexArray( 0 ); // unbind VAO



//CREATE TEXTURE
GLuint textures[2];
glGenTextures(2, textures);

int width, height;
unsigned char * image;

//texture1
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);

image = SOIL_load_image("resources/res/images/green.png", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
// glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
glBindTexture(GL_TEXTURE_2D, textures[0]);


//texture2
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);

image = SOIL_load_image("resources/res/images/img1.png", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
glBindTexture(GL_TEXTURE_2D, textures[1]);



//parameters
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
//filtering
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glGenerateMipmap( GL_TEXTURE_2D );


//loop
while ( !glfwWindowShouldClose( window ) )
{
glfwPollEvents( );

//render
glClearColor( 0.2f, 0.3f, 0.3f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );

//draw triangle
//if
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);


//draw container
glBindVertexArray( VAO );
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
glBindVertexArray( 0 );

glfwSwapBuffers( window );
}

//de-alocated stuff
glDeleteVertexArrays( 1, &VAO );
glDeleteBuffers( 1, &VBO );
glDeleteBuffers( 1, &EBO );

glfwTerminate( );
return EXIT_SUCCESS;
}

这是纹理碎片

    #version 330 core
in vec3 ourColor;
in vec2 TexCoord;

out vec4 color;

uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;
uniform int usetexture = 0;

void main()
{
if (usetexture == 0)
color = texture(ourTexture1, TexCoord);
if (usetexture == 1)
color = texture(ourTexture1, TexCoord);
}

如何正确调用它们并让它们切换?甚至一个纹理都没有显示出来。我想从 SOIL 加载图像在 img1 和 img2 之间切换。但是一直卡住了。有什么建议吗?

最佳答案

您必须将第一个纹理绑定(bind)到纹理单元 0 (GL_TEXTURE0),将第二个纹理绑定(bind)到纹理单元 1 (GL_TEXTURE1):

GLuint textures[2];
int width, height;
unsigned char * image;

glGenTextures(2, textures);

// testure 1
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);

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 );

image = SOIL_load_image("resources/res/images/green.png", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);

// texture 2
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);

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 );

image = SOIL_load_image("resources/res/images/red.png", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);

纹理采样器制服 ourTexture1ourTexture2 的值必须是纹理单元 0 和 1 的编号。在着色器程序对象安装为当前渲染状态的一部分后,可以设置 uniforms 的值 (glUseProgram):

// complie shaders and link shader program (glLinkProgram)
Shader ourShader( "resources/shaders/core.vs", "resources/shaders/core.frag" );
GLint tex1_loc = glGetUniformLocation( ourShader.Program, "ourTexture1" );
GLint tex2_loc = glGetUniformLocation( ourShader.Program, "ourTexture2" );

glUseProgram( ourShader.Program );
glUniform1i( tex1_loc, 0 );
glUniform1i( tex2_loc, 1 );

要在纹理之间选择/切换,我建议使用 glsl 函数 mix .该函数在 2 个值之间进行插值。
第三个参数是 [0.0, 1.0] 范围内的浮点值,它定义了第一个和第二个参数之间的线性插值。如果mix的第三个参数是0.0,函数的结果就是第一个参数。如果是1.0,那么结果就是第二个参数。
这允许您创建两种纹理的混合物或完全利用它们。

片段着色器可能看起来像这样:

#version 330 core
in vec3 ourColor;
in vec2 TexCoord;

out vec4 color;

uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;
uniform float mixtexture;

void main()
{
vec4 color1 = texture(ourTexture1, TexCoord);
vec4 color2 = texture(ourTexture2, TexCoord);
color = mix(color1, color2, mixtexture);
}

要测试代码,您可以使用以下循环,它创建从 ourTexture1ourTexture2 的转换:

GLint mix_loc = glGetUniformLocation( ourShader.Program, "mixtexture" ); 
GLfloat mix_value = 0.0; // in [0.0, 1.0]
while ( !glfwWindowShouldClose( window ) )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glUniform1f(mix_loc, mix_value);
mix_value = mix_value >= 1.0f ? 0.0f : mix_value + 0.01f;

glBindVertexArray( VAO );
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
glBindVertexArray( 0 );

glfwSwapBuffers( window );
glfwPollEvents( );
}

关于c++ - 如何使用 OpenGL 和 C++ 加载多个纹理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51923159/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com