opengl 立方体纹理
来给立方体贴个图。
// glfwTest.cpp : 定义控制台应用程序的入口点。
//
#include "glew.h"
#include <glfw3.h>
#include "common/loadShader.h"
#include "glm.hpp"
#include "ext.hpp"
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(480, 320, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
// Needed in core profile
if( glewInit() != GLEW_OK)
{
glfwTerminate();
return -1;
}
// Our vertices. Tree consecutive floats give a 3D vertex; Three consecutive vertices give a triangle.
// A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.f, 1.f, 1.f,
-1.f,-1.f, 1.f,
1.f,-1.f, 1.f,
1.f,-1.f, 1.f,
1.f, 1.f, 1.f,
-1.f, 1.f, 1.f,
1.f, 1.f, 1.f,
1.f,-1.f, 1.f,
1.f,-1.f,-1.f,
1.f,-1.f,-1.f,
1.f, 1.f,-1.f,
1.f, 1.f, 1.f,
-1.f, 1.f,-1.f,
-1.f, 1.f, 1.f,
1.f, 1.f, 1.f,
1.f, 1.f, 1.f,
1.f, 1.f,-1.f,
-1.f, 1.f,-1.f,
-1.f,-1.f,-1.f,
-1.f,-1.f, 1.f,
1.f,-1.f, 1.f,
1.f,-1.f, 1.f,
1.f,-1.f,-1.f,
-1.f,-1.f,-1.f,
-1.f, 1.f,-1.f,
-1.f,-1.f,-1.f,
1.f,-1.f,-1.f,
1.f,-1.f,-1.f,
1.f, 1.f,-1.f,
-1.f, 1.f,-1.f,
-1.f, 1.f, 1.f,
-1.f, 1.f,-1.f,
-1.f,-1.f,-1.f,
-1.f,-1.f,-1.f,
-1.f,-1.f, 1.f,
-1.f, 1.f, 1.f,
};
//This will identify our vertex buffer
GLuint vertexbuffer;
//Generate 1 buffer,put the resulting identifier in vertexbuffer
glGenBuffers(1,&vertexbuffer);
//The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer);
//Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER,sizeof(g_vertex_buffer_data),g_vertex_buffer_data,GL_STATIC_DRAW);
GLuint Texture = loadBMP_custom("./resource/uvtemplate.bmp");
// One color for each vertex. They were generated randomly.
static const GLfloat g_uv_buffer_data[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f
};
GLuint uvbuffer;
glGenBuffers(1,&uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER,uvbuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(g_uv_buffer_data),g_uv_buffer_data,GL_STATIC_DRAW);
GLuint programID = LoadShaders("./shader/vertex.shader","./shader/fragment.shader");
glUseProgram(programID);
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
/* Loop until the user closes the window */
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit 100 units
//glm::mat4 Projection = glm::ortho(-4.0f/3.0f, 4.0f/3.0f, -1.0f, 1.0f, 0.1f, 100.0f);
glm::mat4 Projection = glm::perspective(45.0f,4.0f/3.0f,0.1f,100.f);
glm::mat4 View = glm::lookAt(
glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
//Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model;// Remember, matrix multiplication is the other way around
// Get a handle for our "MVP" uniform.
// Only at initialisation time.
GLuint MatrixID = glGetUniformLocation(programID,"MVP");
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
// For each model you render, since the MVP will be different (at least the M part)
glUniformMatrix4fv(MatrixID,1,GL_FALSE,&MVP[0][0]);
GLuint TextureID = glGetUniformLocation(programID,"myTextureSampler");
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,Texture);
glUniform1i(TextureID, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER,uvbuffer);
glVertexAttribPointer(
1, // attribute 0. No particular reason for 0, but must match the layout in the shader.
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDrawArrays(GL_TRIANGLES,0,12*3);// Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
加载纹理代码:
#include "loadShader.h"
GLuint LoadShaders(const char* vertex_file_path,const char* fragment_file_path)
{
//Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
//Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path,std::ios::in);
if (VertexShaderStream.is_open())
{
std::string Line = "";
while (getline(VertexShaderStream,Line))
{
VertexShaderCode += "\n" + Line;
}
VertexShaderStream.close();
}
//Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path,std::ios::in);
if (FragmentShaderStream.is_open())
{
std::string Line = "";
while (getline(FragmentShaderStream,Line))
{
FragmentShaderCode += "\n" + Line;
}
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
//compile Vertex Shader
printf("Compiling shader : %s\n",vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID,1,&VertexSourcePointer,NULL);
glCompileShader(VertexShaderID);
// Check vertex Shader
glGetShaderiv(VertexShaderID,GL_COMPILE_STATUS,&Result);
glGetShaderiv(VertexShaderID,GL_INFO_LOG_LENGTH,&InfoLogLength);
std::vector<char> VerTexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID,InfoLogLength,NULL,&VerTexShaderErrorMessage[0]);
fprintf(stdout,"%s\n",&VerTexShaderErrorMessage[0]);
//compile Fragment Shader
printf("Compiling shader : %s\n",fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID,1,&FragmentSourcePointer,NULL);
glCompileShader(FragmentShaderID);
// Check vertex Shader
glGetShaderiv(FragmentShaderID,GL_COMPILE_STATUS,&Result);
glGetShaderiv(FragmentShaderID,GL_INFO_LOG_LENGTH,&InfoLogLength);
std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID,InfoLogLength,NULL,&FragmentShaderErrorMessage[0]);
fprintf(stdout,"%s\n",&FragmentShaderErrorMessage[0]);
//Link the program
fprintf(stdout,"Linking programn");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID,VertexShaderID);
glAttachShader(ProgramID,FragmentShaderID);
glLinkProgram(ProgramID);
//Check the program
glGetProgramiv(ProgramID,GL_LINK_STATUS,&Result);
glGetProgramiv(ProgramID,GL_INFO_LOG_LENGTH,&InfoLogLength);
std::vector<char> ProgramErrorMessage(InfoLogLength);
glGetProgramInfoLog(ProgramID,InfoLogLength,NULL,&ProgramErrorMessage[0]);
fprintf(stdout,"%s\n",&ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
GLuint loadBMP_custom(const char * imagepath)
{
// Data read from the header of the BMP file
unsigned char header[54]; // Each BMP file begins by a 54-bytes header
unsigned int dataPos; //Position in the file where the actual data begins
unsigned int width,height;
unsigned int imageSize; //= width*height*3
// Actual RGB data
unsigned char * data;
//Open the file
FILE * file = fopen(imagepath,"rb");
if (!file)
{
printf("Image could not be openedn");
return 0;
}
if (fread(header,1,54,file) != 54)
{
printf("Not a correct BMP filen");
return false;
}
if (header[0] != 'B' || header[1] != 'M')
{
printf("Not a correct BMP filen");
return 0;
}
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if (imageSize == 0)
{
imageSize = width * height * 3;
}
if (dataPos == 0)
{
dataPos = 54;
}
// Create a buffer
data = new unsigned char [imageSize];
// Read the actual data from the file into the buffer
fread(data,1,imageSize,file);
//Everything is in memory now, the file can be closed
fclose(file);
GLuint textureID;
glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// 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_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// glGenerateMipmap(GL_TEXTURE_2D);
delete[] data;
return textureID;
}
vertex.shader
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
uniform mat4 MVP;
out vec2 UV;
void main(){
vec4 v = vec4(vertexPosition_modelspace,1);
gl_Position = MVP * v;
UV = vertexUV;
}
fragment.shader
#version 330 core
// Interpolated values from the vertex shaders
in vec2 UV;
out vec3 color;
// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;
void main(){
// Output color = color of the texture at the specified UV
color = texture( myTextureSampler,UV).rgb;
}
首先,解析图片,生成纹理。
glGenTextures(1, &textureID);
激活纹理
glBindTexture(GL_TEXTURE_2D, textureID);
图片数据写入到纹理
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
设置取样方式
//normal
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//nice
// 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_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// glGenerateMipmap(GL_TEXTURE_2D);
得到shader中的纹理变量。
GLuint TextureID = glGetUniformLocation(programID,"myTextureSampler");
设置纹理序列
glActiveTexture(GL_TEXTURE0);
激活纹理
glBindTexture(GL_TEXTURE_2D, textureID);
关联shader变量与纹理
glUniform1i(TextureID, 0);
然后,shader中会通过纹理坐标把纹理给贴上去。