[OpenGL]OpenGL頂點着色器、編譯着色器、片段着色器

1.頂點着色器(Vertex Shader)

頂點着色器:幾個可編程着色器中的一個。
OpenGL用GLSL編寫着色器,GLSL看起來很像C語言。

#version 330 core
layout (location = 0) int vec3 aPos;
void main()
{
      gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0)
}

使用in 關鍵字,在頂點着色器中聲明所有的輸入頂點屬性。GLSL有一個向量數據類型,包含1到4個float分量。由於每個頂點都有一個3D座標,我們就創建一個vec3輸入變量aPos。
爲了設置頂點着色器的輸出,我們必須把位置數據賦值給預定義的gl_Position,它在幕後的vec4.
在main函數最後,我們將gl_Position設置的值會成爲該頂點着色器的輸出

編譯頂點着色器

(1)創建一個着色器對象,用ID引用,用glCreateShader創建這個着色器

unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);

我們創建的是一個頂點着色器,傳遞的參數是GL_VERTEX_SHADER
(2)把這個着色器的源碼附加到着色器對象上

glShaderSource(vertexShader, 1, &vertexShader, NULL);
glCompileShader(vertexShader);

原型:

void glShaderSource(GLuint shader​, GLsizei count​, const GLchar **string​, const GLint *length​);

第一個參數:要編譯的着色器對象
第二個參數:指定傳遞的源碼字符串數量
第三個參數:指定指向包含要加載到着色器中的源代碼的字符串的指針數組
第四個參數:指定字符串長度數組

原型:void glCompileShader(GLuint shader​);
指定shader對象去編譯

2.片段着色器(Fragment Shader)

片段着色器:用於計算像素最後的顏色輸出
在計算機圖形中,顏色被表示爲有4個元素的數據,RGBA,當在OpenGL或者GLSL中定義一個顏色,我們把顏色每個分量的強度設置在0.0到1.0之間

#version 330 core
out vec4 FragColor;
void main()
{
       FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f)
}

片段着色器只需要一個輸出變量,這個變量是一個4分向量,表示的是最終的輸出顏色,將其計算出,可以用out關鍵字聲明輸出變量

編譯片段着色器:

unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);

3.着色器程序

着色器程序:多個着色器合併之後並最終鏈接完成的版本
我們要使用編譯的着色器,我們必須把它們鏈接爲一個着色器程序對象,然後再渲染對象的時候激活這個着色器程序
當鏈接着色器至一個程序的時候,它會把每個着色器的輸出鏈接到下個着色器的輸入。

(1)創建一個程序對象

usigned int shaderProgram;
shaderProgram = glCreateProgram();

(2)glCreateProgram函數創建一個程序,並返回該程序的ID引用,需要把之前編譯的着色器附加到程序對象,然後用glLinkProgram鏈接,得到的結果就是一個對象,可以調用glUseProgram函數

gkAttachShader(shaderProgram, vertexShader);
gkAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);

(3)着色器鏈接到程序對象後,刪除着色器

glDeleteShader(vertexShader);
glDeleteShader(fragmentShader)

應用:

#include <GL/glew.h>
#include<gl\glut.h>
#include<iostream>
void MyInit();
void reshape(int w, int h);
void display();

GLuint vboId;
GLuint vaoId;

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(512, 512);
	glutCreateWindow("SHADER_RECTANGLE");
	glewInit();
	MyInit();
	glutReshapeFunc(&reshape);
	glutDisplayFunc(&display);
	glutMainLoop();
	return 0;
}

void MyInit()
{
	glClearColor(0.0,0.0, 0.0,0.0);
	const GLfloat vertices[] = {
		-0.5f,-0.5f,0.0f,1.0f,
		0.5f,-0.5f,0.0f,1.0f,
		0.5f,0.5f,0.0f,1.0f,
		-0.5f,0.5f,0.0f,1.0f,
	};

	//創建VAO對象
	glGenVertexArrays(1, &vaoId);
	glBindVertexArray(vaoId);

	//創建VBO對象
	glGenBuffers(1, &vboId);
	glBindBuffer(GL_ARRAY_BUFFER, vboId);
	//傳入VBO數據
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	//解除VBO綁定
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}


void reshape(int w, int h)
{
	glViewport(0, 0,(GLsizei)w, (GLsizei)h);
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	const char* vertex_shader =
		"#version 330\n"
		"in vec3 aPos;"
		"void main() {"
		"  gl_Position = vec4(aPos, 1.0);"
		"}";

	const char* fragment_shader =
		"#version 330\n"
		"out vec4 FragColor;"
		"void main() {"
		"  FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);"
		"}";
    
    //頂點着色器
	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertex_shader, NULL);
	glCompileShader(vertexShader);
    //片段着色器
	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragment_shader, NULL);
	glCompileShader(fragmentShader);
    //着色器程序
	GLuint shader_programme = glCreateProgram();
	//鏈接着色器
	glAttachShader(shader_programme, fragmentShader);
	glAttachShader(shader_programme, vertexShader);
	glLinkProgram(shader_programme);
	glUseProgram(shader_programme);
	//刪除着色器
	glDeleteShader(fragmentShader);
	glDeleteShader(vertexShader);
	//綁定VBO
	glBindBuffer(GL_ARRAY_BUFFER, vboId);
	glEnableVertexAttribArray(0);
	
	//解釋頂點數據方式
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);

	//繪製模型
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glDisableVertexAttribArray(0);
    glutSwapBuffers();
}

效果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章