几何着色器有意思的地方在于它可以把(一个或多个)顶点转变为完全不同的基本图形(primitive),从而生成比原来多得多的顶点。
main.cpp
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SOIL/SOIL.h>
#include "Shader.h"
#pragma comment(lib, "SOIL.lib")
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glew32s.lib")
#pragma comment (lib, "glfw3.lib")
#pragma comment (lib, "glfw3dll.lib")
#pragma comment (lib, "glew32mxs.lib")
#pragma comment (lib, "assimp.lib")
#define WIDTH 800
#define HEIGH 600
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* pWnd = glfwCreateWindow(WIDTH, HEIGH, "OGL Geometry Shader", nullptr, nullptr);
glfwMakeContextCurrent(pWnd);
glewExperimental = GL_TRUE;
glewInit();
glViewport(0, 0, WIDTH, HEIGH);
GLfloat fPoint[] = {
0.0f, 0.0f, 0.0f, 0.4f, 0.3f, 0.0f,
0.5f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.6f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.2f, -0.5f, 0.0f, 0.0f, 0.4f, 1.0f,
- 0.8f, 0.3f, 0.0f, 1.0f, 0.30f, 1.0f
};
GLuint nVAO, nVBO;
glGenVertexArrays(1, &nVAO);
glBindVertexArray(nVAO);
{
glGenBuffers(1, &nVBO);
glBindBuffer(GL_ARRAY_BUFFER, nVBO);
{
glBufferData(GL_ARRAY_BUFFER, sizeof(fPoint), fPoint, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); // vertex
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6* sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1); // color
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6* sizeof(GLfloat), (GLvoid*)(3 * sizeof(GL_FLOAT)));
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glBindVertexArray(0);
glEnable(GL_PROGRAM_POINT_SIZE);
Shader shader("./Shader/vertex.vx", "./Shader/geo.geo", "./Shader/frag.fg");
//Shader shader("./Shader/vertex.vx", "./Shader/frag.fg");
shader.userShaderProg();
while (!glfwWindowShouldClose(pWnd))
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(nVAO);
{
//glDrawArrays(GL_TRIANGLES, 0, sizeof(fPoint) / sizeof(GLfloat) / 6);
glDrawArrays(GL_POINTS, 0, sizeof(fPoint) / sizeof(GLfloat) / 6);
//glDrawArrays(GL_LINE_STRIP, 0, sizeof(fPoint) / sizeof(GLfloat) / 6);
}
glBindVertexArray(0);
glfwSwapBuffers(pWnd);
}
return 0;
}
Shader
#pragma once
#include <glew.h>
class Shader
{
public:
Shader(const GLchar* pVertexPath, const GLchar* pFragPath);
Shader(const GLchar* pVertexPath, const GLchar* pGeomPath, const GLchar* pFragPath);
~Shader();
public:
void userShaderProg();
GLuint getProg();
private:
void initShader(const GLchar* pVertexPath, const GLchar* pFragPath);
void initShader(const GLchar* pVertexPath, const GLchar* pGeomPath, const GLchar* pFragPath);
private:
GLuint m_nProg;
};
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include "Shader.h"
Shader::Shader(const GLchar* pVertexPath, const GLchar* pFragPath)
{
initShader(pVertexPath, pFragPath);
}
Shader::Shader(const GLchar* pVertexPath, const GLchar* pGeomPath, const GLchar* pFragPath)
{
initShader(pVertexPath, pGeomPath, pFragPath);
}
Shader::~Shader()
{
glDeleteProgram(m_nProg);
}
void Shader::userShaderProg()
{
glUseProgram(m_nProg);
}
GLuint Shader::getProg()
{
return m_nProg;
}
void Shader::initShader(const GLchar* pVertexPath, const GLchar* pFragPath)
{
std::string strVertexCode;
std::string strFragCode;
std::ifstream sVertexShaderF;
std::ifstream sFragShaderF;
sVertexShaderF.exceptions(std::ifstream::badbit);
sFragShaderF.exceptions(std::ifstream::badbit);
try
{
sVertexShaderF.open(pVertexPath);
sFragShaderF.open(pFragPath);
std::stringstream sVertexShaderStream, sGeomShaderStream, sFragShaderStream;
sVertexShaderStream << sVertexShaderF.rdbuf();
sFragShaderStream << sFragShaderF.rdbuf();
sVertexShaderF.close();
sFragShaderF.close();
strVertexCode = sVertexShaderStream.str();
strFragCode = sFragShaderStream.str();
}
catch (const std::exception& e)
{
std::cout << "ERROR ON std::exception" << e.what() << std::endl;
}
catch (const std::ifstream& e)
{
std::cout << "ERROR ON td::ifstream&" << e.rdbuf() << std::endl;
}
const GLchar* pChVertexCode = strVertexCode.c_str();
const GLchar* pChFragCode = strFragCode.c_str();
GLuint nVertexShader, nGeomShader, nFragShader;
GLint nRes = 0;
GLchar chLogInfo[512] = { '\0' };
// Create Vertex Shader Program
nVertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(nVertexShader, 1, &pChVertexCode, nullptr);
glCompileShader(nVertexShader);
glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes);
if (!nRes)
{
glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo);
std::cout << "ERORR ON VERTES SHADER:" << chLogInfo << std::endl;
}
// Create Fragement Shader Program
nFragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(nFragShader, 1, &pChFragCode, nullptr);
glCompileShader(nFragShader);
glGetShaderiv(nFragShader, GL_COMPILE_STATUS, &nRes);
if (!nRes)
{
glGetShaderInfoLog(nFragShader, 512, nullptr, chLogInfo);
std::cout << "ERROR ON FRAGMENT SHADER:" << chLogInfo << std::endl;
}
// Create Shader Programe
m_nProg = glCreateProgram();
glAttachShader(m_nProg, nVertexShader);
glAttachShader(m_nProg, nFragShader);
glLinkProgram(m_nProg);
glGetProgramiv(m_nProg, GL_LINK_STATUS, &nRes);
if (!nRes)
{
glGetProgramInfoLog(m_nProg, 512, nullptr, chLogInfo);
std::cout << "ERROR ON PROGRAME:" << chLogInfo << std::endl;
}
glDeleteShader(nVertexShader);
glDeleteShader(nFragShader);
}
void Shader::initShader(const GLchar* pVertexPath, const GLchar* pGeomPath, const GLchar* pFragPath)
{
std::string strVertexCode;
std::string strGeomCode;
std::string strFragCode;
std::ifstream sVertexShaderF;
std::ifstream sGeomShaderF;
std::ifstream sFragShaderF;
sVertexShaderF.exceptions(std::ifstream::badbit);
sGeomShaderF.exceptions(std::ifstream::badbit);
sFragShaderF.exceptions(std::ifstream::badbit);
try
{
sVertexShaderF.open(pVertexPath);
sGeomShaderF.open(pGeomPath);
sFragShaderF.open(pFragPath);
std::stringstream sVertexShaderStream, sGeomShaderStream, sFragShaderStream;
sVertexShaderStream << sVertexShaderF.rdbuf();
sGeomShaderStream << sGeomShaderF.rdbuf();
sFragShaderStream << sFragShaderF.rdbuf();
sVertexShaderF.close();
sGeomShaderF.close();
sFragShaderF.close();
strVertexCode = sVertexShaderStream.str();
strGeomCode = sGeomShaderStream.str();
strFragCode = sFragShaderStream.str();
}
catch (const std::exception& e)
{
std::cout << "ERROR ON std::exception" << e.what() << std::endl;
}
catch (const std::ifstream& e)
{
std::cout << "ERROR ON td::ifstream&" << e.rdbuf() << std::endl;
}
const GLchar* pChVertexCode = strVertexCode.c_str();
const GLchar* pChGeomCode = strGeomCode.c_str();
const GLchar* pChFragCode = strFragCode.c_str();
GLuint nVertexShader, nGeomShader, nFragShader;
GLint nRes = 0;
GLchar chLogInfo[512] = { '\0' };
// Create Vertex Shader Program
nVertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(nVertexShader, 1, &pChVertexCode, nullptr);
glCompileShader(nVertexShader);
glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes);
if (!nRes)
{
glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo);
std::cout << "ERORR ON VERTES SHADER:" << chLogInfo << std::endl;
}
// Create Geometry Shader Program
nGeomShader = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(nGeomShader, 1, &pChGeomCode, nullptr);
glCompileShader(nGeomShader);
glGetShaderiv(nGeomShader, GL_COMPILE_STATUS, &nRes);
if (!nRes)
{
glGetShaderInfoLog(nGeomShader, 512, nullptr, chLogInfo);
std::cout << "ERORR ON GEOMETRY SHADER:" << chLogInfo << std::endl;
}
// Create Fragement Shader Program
nFragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(nFragShader, 1, &pChFragCode, nullptr);
glCompileShader(nFragShader);
glGetShaderiv(nFragShader, GL_COMPILE_STATUS, &nRes);
if (!nRes)
{
glGetShaderInfoLog(nFragShader, 512, nullptr, chLogInfo);
std::cout << "ERROR ON FRAGMENT SHADER:" << chLogInfo << std::endl;
}
// Create Shader Programe
m_nProg = glCreateProgram();
glAttachShader(m_nProg, nVertexShader);
glAttachShader(m_nProg, nGeomShader);
glAttachShader(m_nProg, nFragShader);
glLinkProgram(m_nProg);
glGetProgramiv(m_nProg, GL_LINK_STATUS, &nRes);
if (!nRes)
{
glGetProgramInfoLog(m_nProg, 512, nullptr, chLogInfo);
std::cout << "ERROR ON PROGRAME:" << chLogInfo << std::endl;
}
glDeleteShader(nVertexShader);
glDeleteShader(nGeomShader);
glDeleteShader(nFragShader);
}
GLSL
vertex.vx
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 inColor;
out VS_OUT {
vec3 color;
} outColor;
void main()
{
gl_PointSize = 6;
gl_Position = vec4(pos, 1.0f);
outColor.color = inColor;
}
geo.geo
#version 330 core
layout (points) in;
layout (triangle_strip, max_vertices = 6) out;
in VS_OUT {
vec3 color;
} inColor[];
out VS_OUT {
vec3 color;
} outColor;
void main()
{
outColor.color = inColor[0].color;
gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0);
EmitVertex();
gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.2, 0.0, 0.0);
EmitVertex();
gl_Position = gl_in[0].gl_Position + vec4(0.3, -0.2, 0.0, 0.0);
EmitVertex();
EndPrimitive();
}
frag.fg
#version 330 core
in VS_OUT {
vec3 color;
} inColor;
out vec4 color;
void main()
{
color = vec4(inColor.color, 1.0f);
}
加入视图功能:
3D图形的表示要经过几个经典的坐标转换,首先从局部到世界坐标系,再从世界坐标系到观察坐标系。
局部坐标系—>世界坐标系—>观察坐标系
顶点着色器中:
//gl_Position = vec4(pos, 1.0f);
gl_Position = projection * view * model * vec4(pos, 1.0f);
main.cpp 中
glm::mat4 view;
view = glm::translate(view, glm::vec3(0.f, 1.0f, 0.0f));
glm::mat4 proj;
proj = glm::perspective(45.0f, 1.0f, 0.1f, 100.0f);
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0f, 0.0f, -5.0f));
GLint nModelLoc = glGetUniformLocation(shader.getProg(), "model");
GLint nViewLoc = glGetUniformLocation(shader.getProg(), "view");
GLint nProjLoc = glGetUniformLocation(shader.getProg(), "projection");
glUniformMatrix4fv(nModelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(nViewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(nProjLoc, 1, GL_FALSE, glm::value_ptr(proj));
源码下载: