在上一个版本基础上,进行了点的旋转,与书籍说的不同我传入的是一个uniform 统一值作为angle。并且去掉了const,因为我在GLSL代码做了一个对angle实时更新操作,故不再是常量,我想矩阵可能会插值 但影响好像没有,除此之外其他地方没啥变化。
// SpaceFlight Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 330
// Incoming per vertex... position and normal
in vec4 vVertex;
in vec4 vColor;
uniform float angle;
uniform mat4 mvpMatrix;
uniform float timeStamp;
out vec4 vStarColor;
out mat2 rotation_matrix;
void main(void)
{
vec4 vNewVertex = vVertex;
vStarColor = vColor;
// Offset by running time, makes it move closer
vNewVertex.z += timeStamp;
// If out of range, adjust
if(vNewVertex.z > -1.0)
vNewVertex.z -= 999.0;
gl_PointSize = 120.0 + (vNewVertex.z / sqrt(-vNewVertex.z));
// If they are very small, fade them up
if(gl_PointSize < 4.0)
vStarColor = smoothstep(0.0, 4.0, gl_PointSize) * vStarColor;
float sin_theta = sin(angle);
float cos_theta = cos(angle);
rotation_matrix = mat2(cos_theta, sin_theta,
-sin_theta, cos_theta);
// Don't forget to transform the geometry!
gl_Position = mvpMatrix * vNewVertex;
}
// SpaceFlight Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 330
out vec4 vFragColor;
in vec4 vStarColor;
in mat2 rotation_matrix;
uniform sampler2D starImage;
void main(void)
{
vec2 pt = gl_PointCoord - vec2(0.5);
vFragColor = texture(starImage, rotation_matrix * pt + vec2(0.5)) * vStarColor;
}
// PointSprites.cpp
// OpenGL SuperBible
// Demonstrates Point Sprites via a flythrough star field
// Program by Richard S. Wright Jr.
#pragma comment(lib, "gltools.lib")
#include <GLTools.h> // OpenGL toolkit
#include <GLFrustum.h>
#include <StopWatch.h>
#include <math.h>
#include <stdlib.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
#define NUM_STARS 10
GLFrustum viewFrustum;
GLBatch starsBatch;
GLuint starFieldShader; // The point sprite shader
GLint locMVP; // The location of the ModelViewProjection matrix uniform
GLint locTimeStamp; // The location of the time stamp
GLint locTexture; // The location of the texture uniform
GLint locAngle; // angle 统一值
GLuint starTexture; // The star texture texture object
// Load a TGA as a 2D Texture. Completely initialize the state
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
GLbyte *pBits;
int nWidth, nHeight, nComponents;
GLenum eFormat;
// Read the texture bits
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
if (pBits == NULL)
return false;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,
eFormat, GL_UNSIGNED_BYTE, pBits);
free(pBits);
if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST)
glGenerateMipmap(GL_TEXTURE_2D);
return true;
}
// This function does any needed initialization on the rendering
// context.
void SetupRC(void)
{
// Background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// A number of shipping drivers are not conformant to the current OpenGL
// spec and require this. NVidia... in particular. The OpenGL specification
// states that this is always "on", in fact you can't enable or disable it
// anymore. Adding this lines "fixes" this on non-conformant drivers, but
// be aware, if you have a pure core (and working correctly) GL context,
//you should not do this
glEnable(GL_POINT_SPRITE);
GLfloat fColors[4][4] = { { 1.0f, 1.0f, 1.0f, 1.0f}, // White
{ 0.67f, 0.68f, 0.82f, 1.0f}, // Blue Stars
{ 1.0f, 0.5f, 0.5f, 1.0f}, // Reddish
{ 1.0f, 0.82f, 0.65f, 1.0f} }; // Orange
// Randomly place the stars in their initial positions, and pick a random color
starsBatch.Begin(GL_POINTS, NUM_STARS);
for (int i = 0; i < NUM_STARS; i++)
{
int iColor = 0; // All stars start as white
// One in five will be blue
if (rand() % 5 == 1)
iColor = 1;
// One in 50 red
if (rand() % 50 == 1)
iColor = 2;
// One in 100 is amber
if (rand() % 100 == 1)
iColor = 3;
starsBatch.Color4fv(fColors[iColor]);
M3DVector3f vPosition;
vPosition[0] = float(3000 - (rand() % 6000)) * 0.1f;
vPosition[1] = float(3000 - (rand() % 6000)) * 0.1f;
vPosition[2] = -float(rand() % 1000) - 1.0f; // -1 to -1000.0f
starsBatch.Vertex3fv(vPosition);
}
starsBatch.End();
starFieldShader = gltLoadShaderPairWithAttributes("SpaceFlight.vp", "SpaceFlight.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex",
GLT_ATTRIBUTE_COLOR, "vColor");
locMVP = glGetUniformLocation(starFieldShader, "mvpMatrix");
locTexture = glGetUniformLocation(starFieldShader, "starImage");
locTimeStamp = glGetUniformLocation(starFieldShader, "timeStamp");
locAngle = glGetUniformLocation(starFieldShader, "angle");
glGenTextures(1, &starTexture);
glBindTexture(GL_TEXTURE_2D, starTexture);
LoadTGATexture("Star.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
}
// Cleanup
void ShutdownRC(void)
{
glDeleteTextures(1, &starTexture);
}
// Called to draw scene
void RenderScene(void)
{
static CStopWatch timer;
// Clear the window and the depth buffer
glClear(GL_COLOR_BUFFER_BIT);
// Turn on additive blending
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
// Let the vertex program determine the point size
glEnable(GL_PROGRAM_POINT_SIZE);
// Bind to our shader, set uniforms
glUseProgram(starFieldShader);
glUniformMatrix4fv(locMVP, 1, GL_FALSE, viewFrustum.GetProjectionMatrix());
glUniform1i(locTexture, 0);
// fTime goes from 0.0 to 999.0 and recycles
float fTime = timer.GetElapsedSeconds() * 100.0f;
fTime = fmod(fTime, 999.0f);
glUniform1f(locTimeStamp, fTime);
float fAngle = timer.GetElapsedSeconds() * 100.0f;
fAngle = fmod(fAngle, 360.0f);
glUniform1f(locAngle, fAngle);
// Draw the stars
starsBatch.Draw();
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, 1000.0f);
}
///
// 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("Spaced Out");
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;
}