【OpenGL】几何着色器——生成几何图形Tessellate案例

原理:从正方体的表面对角线生成一个新顶点,表面的2个三角形顶点(a,b,c)与d构成新的三角形带,并且它们顶点与原点的距离是相等的。使用归一化来达到相同距离。

FlatShader.fs

// Normal visualizer
// Fragment Shader
// Graham Sellers
// OpenGL SuperBible
#version 150

precision highp float;

in Fragment
{
    vec4 color;
} fragment;

out vec4 output_color;

void main(void)
{
    output_color = fragment.color;
}

 FlatShader.vs

// Cell lighting Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 150

precision highp float;

// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;

uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;

out Fragment
{
    vec4 color;
} fragment;

void main(void)
{
    // Get surface normal in eye coordinates
    vec3 vEyeNormal = normalMatrix * vNormal;

    // Get vertex position in eye coordinates
    vec4 vPosition4 = mvMatrix * vVertex;
    vec3 vPosition3 = vPosition4.xyz / vPosition4.w;

    // Get vector to light source
    vec3 vLightDir = normalize(vLightPosition - vPosition3);

    // Dot product gives us diffuse intensity
    fragment.color = vec4(0.0, 0.0, 0.6, 1.0) * max(0.0, dot(vEyeNormal, vLightDir));

    gl_Position = mvpMatrix * vVertex;
}

GSTessellate.gs

// Normal Visualizer
// Geometry Shader
// Graham Sellers
// OpenGL SuperBible
#version 150

precision highp float;

layout (triangles) in;
layout (triangle_strip, max_vertices = 6) out;

in Vertex
{
    vec3 normal;
    vec4 color;
} vertex[];

out vec4 color;

uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;

void main(void)
{
    int n;
    vec3 a = normalize(gl_in[0].gl_Position.xyz);
    vec3 b = normalize(gl_in[1].gl_Position.xyz);
    vec3 c = normalize(gl_in[2].gl_Position.xyz);

    vec3 d = normalize(b + c);

    gl_Position = mvpMatrix * vec4(b, 1.0);
    color = vec4(1.0, 0.0, 0.0, 1.0);
    EmitVertex();
    gl_Position = mvpMatrix * vec4(d, 1.0);
    color = vec4(0.0, 1.0, 0.0, 1.0);
    EmitVertex();
    gl_Position = mvpMatrix * vec4(a, 1.0);
    color = vec4(0.0, 0.0, 1.0, 1.0);
    EmitVertex();
    gl_Position = mvpMatrix * vec4(c, 1.0);
    color = vec4(1.0, 0.0, 1.0, 1.0);
    EmitVertex();

    EndPrimitive();
}

 GSTessellate.fs

// Normal visualizer
// Fragment Shader
// Graham Sellers
// OpenGL SuperBible
#version 150

precision highp float;

in vec4 color;

out vec4 output_color;

void main(void)
{
    output_color = color;
}

 GSTessellate.vs

// Cell lighting Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 150

precision highp float;

// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;

out Vertex
{
    vec3 normal;
    vec4 color;
} vertex;

uniform vec3 vLightPosition;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;

void main(void)
{
    // Get surface normal in eye coordinates
    vec3 vEyeNormal = normalMatrix * vNormal;

    // Get vertex position in eye coordinates
    vec4 vPosition4 = mvMatrix * vVertex;
    vec3 vPosition3 = vPosition4.xyz / vPosition4.w;

    // Get vector to light source
    vec3 vLightDir = normalize(vLightPosition - vPosition3);

    // Dot product gives us diffuse intensity
    vertex.color = vec4(0.3, 0.3, 0.9, 1.0) * max(0.0, dot(vEyeNormal, vLightDir));

    gl_Position = vVertex;
    vertex.normal = vNormal;
}
// Tessellation using Geometry Shaders
// OpenGL SuperBible 5th Edition
// Program by Graham Sellers

// OpenGL toolkit
#pragma comment(lib, "gltools.lib")
#include <GLTools.h>
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <Stopwatch.h>

#include <math.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

#ifdef _MSC_VER
#pragma comment (lib, "GLTools.lib")
#endif /* _MSC_VER */

static GLFrame              viewFrame;
static GLFrustum            viewFrustum;
static GLMatrixStack        modelViewMatrix;
static GLMatrixStack        projectionMatrix;
static GLGeometryTransform  transformPipeline;
static GLShaderManager      shaderManager;

static GLuint               tessellateProgram;      // The dissolving light shader
static GLint                locMVP;                 // The location of the ModelViewProjection matrix uniform
static GLint                locMV;                  // The location of the ModelView matrix uniform
static GLint                locNM;                  // The location of the Normal matrix uniform

static GLuint               vao;
static GLuint               vertex_buffer;
static GLuint               element_buffer;

// This function does any needed initialization on the rendering context.
void SetupRC(void)
{
	// Background
	glClearColor(0.2f, 0.2f, 0.3f, 1.0f);

	glEnable(GL_DEPTH_TEST);

	shaderManager.InitializeStockShaders();
	viewFrame.MoveForward(4.0f);

	tessellateProgram = gltLoadShaderTripletWithAttributes("GSTessellate.vs",
		"GSTessellate.gs",
		"GSTessellate.fs",
		2,
		GLT_ATTRIBUTE_VERTEX, "vVertex",
		GLT_ATTRIBUTE_NORMAL, "vNormal");

	locMVP = glGetUniformLocation(tessellateProgram, "mvpMatrix");
	locMV = glGetUniformLocation(tessellateProgram, "mvMatrix");
	locNM = glGetUniformLocation(tessellateProgram, "normalMatrix");

	static const GLfloat vertices[] =
	{
		-1.0f, -1.0f, -1.0f,        // A
		-1.0f, -1.0f,  1.0f,        // B
		-1.0f,  1.0f, -1.0f,        // C
		-1.0f,  1.0f,  1.0f,        // D
		 1.0f, -1.0f, -1.0f,        // E
		 1.0f, -1.0f,  1.0f,        // F
		 1.0f,  1.0f, -1.0f,        // G
		 1.0f,  1.0f,  1.0f         // H
	};

	static const GLshort indices[] =
	{
		0, 1, 2,
		3, 2, 1,
		1, 5, 3,
		7, 3, 5,
		5, 4, 7,
		6, 7, 4,
		4, 0, 6,
		2, 6, 0,
		4, 5, 0,
		1, 0, 5,
		3, 7, 2,
		6, 2, 7
	};

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glGenBuffers(1, &vertex_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
	glEnableVertexAttribArray(0);
	glGenBuffers(1, &element_buffer);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}

// Cleanup
void ShutdownRC(void)
{
	glBindVertexArray(0);
	glDeleteVertexArrays(1, &vao);
	glDeleteBuffers(1, &element_buffer);
	glDeleteBuffers(1, &vertex_buffer);
}

// Called to draw scene
void RenderScene(void)
{
	static CStopWatch rotTimer;

	// Clear the window and the depth buffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	modelViewMatrix.PushMatrix(viewFrame);
	modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 20.0f, 0.0f, 1.0f, 0.0f);
	modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 17.0f, 1.0f, 0.0f, 0.0f);

	GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f };
	GLfloat vAmbientColor[] = { 0.1f, 0.1f, 0.1f, 1.0f };
	GLfloat vDiffuseColor[] = { 0.1f, 1.0f, 0.1f, 1.0f };
	GLfloat vSpecularColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };

	glUseProgram(tessellateProgram);
	glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
	glUniformMatrix4fv(locMV, 1, GL_FALSE, transformPipeline.GetModelViewMatrix());
	glUniformMatrix3fv(locNM, 1, GL_FALSE, transformPipeline.GetNormalMatrix());

	glDisable(GL_CULL_FACE);
	glBindVertexArray(vao);
	glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, NULL);

	modelViewMatrix.PopMatrix();

	glutSwapBuffers();
	glutPostRedisplay();
}

void ChangeSize(int w, int h)
{
	// Prevent a divide by zero
	if (h == 0)
		h = 1;

	// Set Viewport to window dimensions
	glViewport(0, 0, w, h);

	viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 100.0f);

	projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
	transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}

///
// Main entry point for GLUT based programs
int main(int argc, char* argv[])
{
	gltSetWorkingDirectory(argv[0]);

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Geometry Shader Tessellation");
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);

	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
	}

	SetupRC();
	glutMainLoop();
	ShutdownRC();
	return 0;
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值