給一個正方形新增紋理
----------------------------------------------------------
區分: 頂點 Vertex 與 頂點位置 Vertex Position 與 頂點屬性 Vertex Attribute
---------------------------------------------------------
頂點資料是一個統稱概念,可以包含多個部分,比如(頂點位置,頂點顏色,頂點對應的紋理座標,等等)。
-----------------------------------------------------------
例如 一個頂點(Position, Color, TexCoord, ....)
float Position[3];//因為3D空間中一個座標位置有三個分量
float Color[3]; //顏色具有三個分量/資料 R G B
float TexCoord[2];// 紋理座標是二維空間,該變數一般用於對紋理圖片的顏色取樣使用
...//還可以定義其它資料,如頂點法線float Normal[3],表示該頂點處的法向量<<<<獨有概念,數學中一個點沒有法向量
///綜上 Position Color TexCoord 可以構成一個頂點資料。。。還可以自定義其它頂點屬性,並進行相應的描述。。
///一個頂點的記憶體大小為 sizeof(float) * 3 + sizeof(float) * 3 + sizeof(float) * 2
///頂點間的步長為?
-----------------------------------------------
float vertices[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0};
vertices 為頂點資料,有3個屬性。
vertices 的屬性為頂點的位置 (1.0f, 0.0f, 0.0f) 頂點的顏色(1.0f, 0.0f, 1.0f) 頂點的紋理座標(1.0f, 1.0f)
vertices 共有1個頂點
vertices 要傳送到vertex shader中具有開啟3個位置,對應3個變數
vertices 的頂點資料可以來自檔案、圖片等。(高總總結的文字)
下面是例項:
////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "ogldev_util.h"
#include "ogldev_glut_backend.h"
#include "ogldev_pipeline.h"
#include "ogldev_camera.h"
#include "ogldev_texture.h"
GLuint VBO;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";
GLuint gSampler;
Texture* pTexture = NULL;
struct Vertex
{
Vector3f m_pos;
Vector3f m_tex;
Vector2f m_tex1;
Vertex() {}
Vertex(Vector3f pos, Vector3f tex,Vector2f tex1)
{
m_pos = pos;
m_tex = tex;
m_tex1 = tex1;
}
};
static void RenderSceneCB()
{
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)24);
pTexture->Bind(GL_TEXTURE0);
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glutSwapBuffers();
}
static void InitializeGlutCallbacks()
{
glutDisplayFunc(RenderSceneCB);
}
//正方形座標,頂點顏色座標,貼圖
static void CreateVertexBuffer()
{
double n = 0.5;
Vertex Vertices[4] =
{
Vertex(Vector3f(-0.5f, 0.5f, 0.0f), Vector3f(1.0f, 1.0f, 0.0f), Vector2f(0.0f, 0.0f)),
Vertex(Vector3f(0.5f, 0.5f, 0.0f), Vector3f(0.5f, 0.5f, 1.0f), Vector2f(2.0f,0.0f)),
Vertex(Vector3f(0.5f, -0.5f, 0.0f), Vector3f(1.0f, 0.0f, 0.0f), Vector2f(2.0f, 1.0f)),
Vertex(Vector3f(-0.5f, -0.5f, 0.0f), Vector3f(0.0f, 1.0f, 0.0f), Vector2f(0.0f, 1.0f))
};
//寫入控制代碼
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
GLuint ShaderObj = glCreateShader(ShaderType);
if (ShaderObj == 0) {
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit(0);
}
const GLchar* p[1];
p[0] = pShaderText;
GLint Lengths[1];
Lengths[0]= strlen(pShaderText);
glShaderSource(ShaderObj, 1, p, Lengths);
glCompileShader(ShaderObj);
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
exit(1);
}
glAttachShader(ShaderProgram, ShaderObj);
}
//建立一個shader程式物件來開始我們的著色器工程.
static void CompileShaders()
{
GLuint ShaderProgram = glCreateProgram();
if (ShaderProgram == 0) {
fprintf(stderr, "Error creating shader program\n");
exit(1);
}
string vs, fs;
if (!ReadFile(pVSFileName, vs)) {
exit(1);//異常退出
};
if (!ReadFile(pFSFileName, fs)) {
exit(1);//異常退出
};
AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
//連結操作
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == 0) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
exit(1);
}//檢查程式相關的錯誤
//管線狀態程式是否能夠成功執行
glValidateProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
if (!Success) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
exit(1);
}
gSampler = glGetUniformLocation(ShaderProgram, "gSampler");
assert(gSampler != 0xFFFFFFFF);
//將連結之後的 Shader 程式物件新增到渲染管線中
glUseProgram(ShaderProgram);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize(1024, 768);
glutInitWindowPosition(100, 100);
glutCreateWindow("Tutorial 04");
InitializeGlutCallbacks();
// Must be done after glut is initialized!
GLenum res = glewInit();
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
printf("GL version: %s\n", glGetString(GL_VERSION));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
CreateVertexBuffer();
CompileShaders();
//讀入圖片資料glGetUniformLocation()傳入著色器
glUniform1i(gSampler, 0);
pTexture = new Texture(GL_TEXTURE_2D, "mn2.png");
if (!pTexture->Load()) {
return 1;
}
glutMainLoop();
return 0;
}