太阳、地球和月亮的显示
sphere.h
#include <cmath>
#include <vector>
#include <glm\glm.hpp>
class Sphere
{
private:
int numVertices;
int numIndices;
std::vector<int> indices;
std::vector<glm::vec3> vertices;
std::vector<glm::vec2> texCoords;
std::vector<glm::vec3> normals;
std::vector<glm::vec3> tangents;
void init(int);
float toRadians(float degrees);
public:
Sphere();
Sphere(int prec);
int getNumVertices();
int getNumIndices();
std::vector<int> getIndices();
std::vector<glm::vec3> getVertices();
std::vector<glm::vec2> getTexCoords();
std::vector<glm::vec3> getNormals();
std::vector<glm::vec3> getTangents();
};
sphere.cpp
#include <cmath>
#include <vector>
#include <iostream>
#include <glm\glm.hpp>
#include "Sphere.h"
using namespace std;
Sphere::Sphere() {
init(48);
}
Sphere::Sphere(int prec) {
init(prec);
}
float Sphere::toRadians(float degrees) { return (degrees * 2.0f * 3.14159f) / 360.0f; }
void Sphere::init(int prec) {
numVertices = (prec + 1) * (prec + 1);
numIndices = prec * prec * 6;
for (int i = 0; i < numVertices; i++) { vertices.push_back(glm::vec3()); }
for (int i = 0; i < numVertices; i++) { texCoords.push_back(glm::vec2()); }
for (int i = 0; i < numVertices; i++) { normals.push_back(glm::vec3()); }
for (int i = 0; i < numVertices; i++) { tangents.push_back(glm::vec3()); }
for (int i = 0; i < numIndices; i++) { indices.push_back(0); }
// calculate triangle vertices
for (int i = 0; i <= prec; i++) {
for (int j = 0; j <= prec; j++) {
float y = (float)cos(toRadians(180.0f - i * 180.0f / prec));
float x = -(float)cos(toRadians(j*360.0f / prec))*(float)abs(cos(asin(y)));
float z = (float)sin(toRadians(j*360.0f / (float)(prec)))*(float)abs(cos(asin(y)));
vertices[i*(prec + 1) + j] = glm::vec3(x, y, z);
texCoords[i*(prec + 1) + j] = glm::vec2(((float)j / prec), ((float)i / prec));
normals[i*(prec + 1) + j] = glm::vec3(x, y, z);
// calculate tangent vector
if (((x == 0) && (y == 1) && (z == 0)) || ((x == 0) && (y == -1) && (z == 0))) {
tangents[i*(prec + 1) + j] = glm::vec3(0.0f, 0.0f, -1.0f);
}
else {
tangents[i*(prec + 1) + j] = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(x, y, z));
}
}
}
// calculate triangle indices
for (int i = 0; i<prec; i++) {
for (int j = 0; j<prec; j++) {
indices[6 * (i*prec + j) + 0] = i*(prec + 1) + j;
indices[6 * (i*prec + j) + 1] = i*(prec + 1) + j + 1;
indices[6 * (i*prec + j) + 2] = (i + 1)*(prec + 1) + j;
indices[6 * (i*prec + j) + 3] = i*(prec + 1) + j + 1;
indices[6 * (i*prec + j) + 4] = (i + 1)*(prec + 1) + j + 1;
indices[6 * (i*prec + j) + 5] = (i + 1)*(prec + 1) + j;
}
}
}
int Sphere::getNumVertices() { return numVertices; }
int Sphere::getNumIndices() { return numIndices; }
std::vector<int> Sphere::getIndices() { return indices; }
std::vector<glm::vec3> Sphere::getVertices() { return vertices; }
std::vector<glm::vec2> Sphere::getTexCoords() { return texCoords; }
std::vector<glm::vec3> Sphere::getNormals() { return normals; }
std::vector<glm::vec3> Sphere::getTangents() { return tangents; }
Utils.h
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <SOIL2\soil2.h>
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <vector>
#include <glm\glm.hpp>
#include <glm\gtc\type_ptr.hpp>
#include <glm\gtc\matrix_transform.hpp>
class Utils
{
private:
static std::string readShaderFile(const char *filePath);
static void printShaderLog(GLuint shader);
static void printProgramLog(int prog);
static GLuint prepareShader(int shaderTYPE, const char *shaderPath);
static int finalizeShaderProgram(GLuint sprogram);
public:
Utils();
static bool checkOpenGLError();
static GLuint createShaderProgram(const char *vp, const char *fp);
static GLuint createShaderProgram(const char *vp, const char *gp, const char *fp);
static GLuint createShaderProgram(const char *vp, const char *tCS, const char* tES, const char *fp);
static GLuint createShaderProgram(const char *vp, const char *tCS, const char* tES, char *gp, const char *fp);
static GLuint loadTexture(const char *texImagePath);
static GLuint loadCubeMap(const char *mapDir);
static float* goldAmbient();
static float* goldDiffuse();
static float* goldSpecular();
static float goldShininess();
static float* silverAmbient();
static float* silverDiffuse();
static float* silverSpecular();
static float silverShininess();
static float* bronzeAmbient();
static float* bronzeDiffuse();
static float* bronzeSpecular();
static float bronzeShininess();
};
Utils.cpp
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <SOIL2\soil2.h>
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <glm\glm.hpp>
#include <glm\gtc\type_ptr.hpp> // glm::value_ptr
#include <glm\gtc\matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
#include "Utils.h"
using namespace std;
Utils::Utils() {}
string Utils::readShaderFile(const char *filePath) {
string content;
ifstream fileStream(filePath, ios::in);
string line = "";
while (!fileStream.eof()) {
getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
bool Utils::checkOpenGLError() {
bool foundError = false;
int glErr = glGetError();
while (glErr != GL_NO_ERROR) {
cout << "glError: " << glErr << endl;
foundError = true;
glErr = glGetError();
}
return foundError;
}
void Utils::printShaderLog(GLuint shader) {
int len = 0;
int chWrittn = 0;
char *log;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len > 0) {
log = (char *)malloc(len);
glGetShaderInfoLog(shader, len, &chWrittn, log);
cout << "Shader Info Log: " << log << endl;
free(log);
}
}
GLuint Utils::prepareShader(int shaderTYPE, const char *shaderPath)
{ GLint shaderCompiled;
string shaderStr = readShaderFile(shaderPath);
const char *shaderSrc = shaderStr.c_str();
GLuint shaderRef = glCreateShader(shaderTYPE);
glShaderSource(shaderRef, 1, &shaderSrc, NULL);
glCompileShader(shaderRef);
checkOpenGLError();
glGetShaderiv(shaderRef, GL_COMPILE_STATUS, &shaderCompiled);
if (shaderCompiled != 1)
{ if (shaderTYPE == 35633) cout << "Vertex ";
if (shaderTYPE == 36488) cout << "Tess Control ";
if (shaderTYPE == 36487) cout << "Tess Eval ";
if (shaderTYPE == 36313) cout << "Geometry ";
if (shaderTYPE == 35632) cout << "Fragment ";
cout << "shader compilation error." << endl;
printShaderLog(shaderRef);
}
return shaderRef;
}
void Utils::printProgramLog(int prog) {
int len = 0;
int chWrittn = 0;
char *log;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
if (len > 0) {
log = (char *)malloc(len);
glGetProgramInfoLog(prog, len, &chWrittn, log);
cout << "Program Info Log: " << log << endl;
free(log);
}
}
int Utils::finalizeShaderProgram(GLuint sprogram)
{ GLint linked;
glLinkProgram(sprogram);
checkOpenGLError();
glGetProgramiv(sprogram, GL_LINK_STATUS, &linked);
if (linked != 1)
{ cout << "linking failed" << endl;
printProgramLog(sprogram);
}
return sprogram;
}
GLuint Utils::createShaderProgram(const char *vp, const char *fp) {
GLuint vShader = prepareShader(GL_VERTEX_SHADER, vp);
GLuint fShader = prepareShader(GL_FRAGMENT_SHADER, fp);
GLuint vfprogram = glCreateProgram();
glAttachShader(vfprogram, vShader);
glAttachShader(vfprogram, fShader);
finalizeShaderProgram(vfprogram);
return vfprogram;
}
GLuint Utils::createShaderProgram(const char *vp, const char *gp, const char *fp) {
GLuint vShader = prepareShader(GL_VERTEX_SHADER, vp);
GLuint gShader = prepareShader(GL_GEOMETRY_SHADER, gp);
GLuint fShader = prepareShader(GL_FRAGMENT_SHADER, fp);
GLuint vgfprogram = glCreateProgram();
glAttachShader(vgfprogram, vShader);
glAttachShader(vgfprogram, gShader);
glAttachShader(vgfprogram, fShader);
finalizeShaderProgram(vgfprogram);
return vgfprogram;
}
GLuint Utils::createShaderProgram(const char *vp, const char *tCS, const char* tES, const char *fp) {
GLuint vShader = prepareShader(GL_VERTEX_SHADER, vp);
GLuint tcShader = prepareShader(GL_TESS_CONTROL_SHADER, tCS);
GLuint teShader = prepareShader(GL_TESS_EVALUATION_SHADER, tES);
GLuint fShader = prepareShader(GL_FRAGMENT_SHADER, fp);
GLuint vtfprogram = glCreateProgram();
glAttachShader(vtfprogram, vShader);
glAttachShader(vtfprogram, tcShader);
glAttachShader(vtfprogram, teShader);
glAttachShader(vtfprogram, fShader);
finalizeShaderProgram(vtfprogram);
return vtfprogram;
}
GLuint Utils::createShaderProgram(const char *vp, const char *tCS, const char* tES, char *gp, const char *fp) {
GLuint vShader = prepareShader(GL_VERTEX_SHADER, vp);
GLuint tcShader = prepareShader(GL_TESS_CONTROL_SHADER, tCS);
GLuint teShader = prepareShader(GL_TESS_EVALUATION_SHADER, tES);
GLuint gShader = prepareShader(GL_GEOMETRY_SHADER, gp);
GLuint fShader = prepareShader(GL_FRAGMENT_SHADER, fp);
GLuint vtgfprogram = glCreateProgram();
glAttachShader(vtgfprogram, vShader);
glAttachShader(vtgfprogram, tcShader);
glAttachShader(vtgfprogram, teShader);
glAttachShader(vtgfprogram, gShader);
glAttachShader(vtgfprogram, fShader);
finalizeShaderProgram(vtgfprogram);
return vtgfprogram;
}
GLuint Utils::loadCubeMap(const char *mapDir) {
GLuint textureRef;
string xp = mapDir; xp = xp + "/xp.jpg";
string xn = mapDir; xn = xn + "/xn.jpg";
string yp = mapDir; yp = yp + "/yp.jpg";
string yn = mapDir; yn = yn + "/yn.jpg";
string zp = mapDir; zp = zp + "/zp.jpg";
string zn = mapDir; zn = zn + "/zn.jpg";
textureRef = SOIL_load_OGL_cubemap(xp.c_str(), xn.c_str(), yp.c_str(), yn.c_str(), zp.c_str(), zn.c_str(),
SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS);
if (textureRef == 0) cout << "didnt find cube map image file" << endl;
// glBindTexture(GL_TEXTURE_CUBE_MAP, textureRef);
// reduce seams
// glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
return textureRef;
}
GLuint Utils::loadTexture(const char *texImagePath)
{ GLuint textureRef;
textureRef = SOIL_load_OGL_texture(texImagePath, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
if (textureRef == 0) cout << "didnt find texture file " << texImagePath << endl;
// ----- mipmap/anisotropic section
glBindTexture(GL_TEXTURE_2D, textureRef);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
if (glewIsSupported("GL_EXT_texture_filter_anisotropic")) {
GLfloat anisoset = 0.0f;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisoset);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoset);
}
// ----- end of mipmap/anisotropic section
return textureRef;
}
// GOLD material - ambient, diffuse, specular, and shininess
float* Utils::goldAmbient() { static float a[4] = { 0.2473f, 0.1995f, 0.0745f, 1 }; return (float*)a; }
float* Utils::goldDiffuse() { static float a[4] = { 0.7516f, 0.6065f, 0.2265f, 1 }; return (float*)a; }
float* Utils::goldSpecular() { static float a[4] = { 0.6283f, 0.5559f, 0.3661f, 1 }; return (float*)a; }
float Utils::goldShininess() { return 51.2f; }
// SILVER material - ambient, diffuse, specular, and shininess
float* Utils::silverAmbient() { static float a[4] = { 0.1923f, 0.1923f, 0.1923f, 1 }; return (float*)a; }
float* Utils::silverDiffuse() { static float a[4] = { 0.5075f, 0.5075f, 0.5075f, 1 }; return (float*)a; }
float* Utils::silverSpecular() { static float a[4] = { 0.5083f, 0.5083f, 0.5083f, 1 }; return (float*)a; }
float Utils::silverShininess() { return 51.2f; }
// BRONZE material - ambient, diffuse, specular, and shininess
float* Utils::bronzeAmbient() { static float a[4] = { 0.2125f, 0.1275f, 0.0540f, 1 }; return (float*)a; }
float* Utils::bronzeDiffuse() { static float a[4] = { 0.7140f, 0.4284f, 0.1814f, 1 }; return (float*)a; }
float* Utils::bronzeSpecular() { static float a[4] = { 0.3936f, 0.2719f, 0.1667f, 1 }; return (float*)a; }
float Utils::bronzeShininess() { return 25.6f; }
main.cpp
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <SOIL2\soil2.h>
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <stack>
#include <glm\glm.hpp>
#include <glm\gtc\type_ptr.hpp> // glm::value_ptr
#include <glm\gtc\matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
#include "Utils.h"
#include "Sphere.h"
using namespace std;
#define numVAOs 1
#define numVBOs 3
float cameraX, cameraY, cameraZ;
float sphLocX, sphLocY, sphLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];
GLuint earthTexture;
GLuint moonTexture;
GLuint sunTexture;
float rotAmt = 0.0f;
// variable allocation for display
GLuint mvLoc, projLoc;
int width, height;
float aspect;
glm::mat4 pMat, vMat, mMat, mvMat;
stack<glm::mat4> mvStack;
Sphere mySphere = Sphere(48);
void setupVertices(void) {
std::vector<int> ind = mySphere.getIndices();
std::vector<glm::vec3> vert = mySphere.getVertices();
std::vector<glm::vec2> tex = mySphere.getTexCoords();
std::vector<glm::vec3> norm = mySphere.getNormals();
std::vector<float> pvalues; //顶点位置
std::vector<float> tvalues; //纹理坐标
std::vector<float> nvalues; //法向量
int numIndices = mySphere.getNumIndices();
for (int i = 0; i < numIndices; i++) {
pvalues.push_back((vert[ind[i]]).x);
pvalues.push_back((vert[ind[i]]).y);
pvalues.push_back((vert[ind[i]]).z);
tvalues.push_back((tex[ind[i]]).s);
tvalues.push_back((tex[ind[i]]).t);
nvalues.push_back((norm[ind[i]]).x);
nvalues.push_back((norm[ind[i]]).y);
nvalues.push_back((norm[ind[i]]).z);
}
glGenVertexArrays(1, vao);
glBindVertexArray(vao[0]);
glGenBuffers(numVBOs, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, pvalues.size() * 4, &pvalues[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, tvalues.size() * 4, &tvalues[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ARRAY_BUFFER, nvalues.size() * 4, &nvalues[0], GL_STATIC_DRAW);
}
void init(GLFWwindow* window) {
renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");
cameraX = 0.0f; cameraY = 0.0f; cameraZ = 2.0f;
sphLocX = 0.0f; sphLocY = 0.0f; sphLocZ = -1.0f;
glfwGetFramebufferSize(window, &width, &height);
aspect = (float)width / (float)height;
pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
setupVertices();
sunTexture = Utils::loadTexture("sunmap.jpg");
earthTexture = Utils::loadTexture("earth.jpg");
moonTexture = Utils::loadTexture("moon.jpg");
}
void display(GLFWwindow* window, double currentTime) {
glClear(GL_DEPTH_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(renderingProgram);
mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");
vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));
mvStack.push(vMat);
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
// ----------------------sun
mvStack.push(mvStack.top());
mvStack.top() *= glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
mvStack.push(mvStack.top());
mvStack.top() *= rotate(glm::mat4(1.0f), (float)currentTime, glm::vec3(0.0, 1.0, 0.0));
mvStack.top() *= scale(glm::mat4(1.0f), glm::vec3(0.25f, 0.25f, 0.25f));
glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvStack.top()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sunTexture);
glEnable(GL_CULL_FACE); //调整深度
glFrontFace(GL_CCW);
glDrawArrays(GL_TRIANGLES, 0, mySphere.getNumIndices());
mvStack.pop();
//-----------------------planet
mvStack.push(mvStack.top());
mvStack.top() *= glm::translate(glm::mat4(1.0f), glm::vec3(sin((float)currentTime)*1.0, 0.0f, cos((float)currentTime)*1.0));
mvStack.push(mvStack.top());
mvStack.top() *= rotate(glm::mat4(1.0f), (float)currentTime*3, glm::vec3(0.0, 1.0, 0.0));
mvStack.top() *= scale(glm::mat4(1.0f), glm::vec3(0.1f, 0.1f, 0.1f));
glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvStack.top()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, earthTexture);
glEnable(GL_CULL_FACE); //调整深度
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDrawArrays(GL_TRIANGLES, 0, mySphere.getNumIndices());
mvStack.pop();
//-----------------------moon
mvStack.push(mvStack.top());
mvStack.top() *= glm::translate(glm::mat4(1.0f), glm::vec3(sin((float)currentTime*7)*0.15, 0.0f, cos((float)currentTime*7)*0.15));
mvStack.top() *= rotate(glm::mat4(1.0f), (float)currentTime, glm::vec3(0.0, 0.0, 1.0));
mvStack.top() *= scale(glm::mat4(1.0f), glm::vec3(0.02f, 0.02f, 0.02f));
glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvStack.top()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, moonTexture);
glEnable(GL_CULL_FACE); //调整深度
glFrontFace(GL_CCW);
glDrawArrays(GL_TRIANGLES, 0, mySphere.getNumIndices());
mvStack.pop();
}
void window_size_callback(GLFWwindow* win, int newWidth, int newHeight) {
aspect = (float)newWidth / (float)newHeight;
glViewport(0, 0, newWidth, newHeight);
pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
}
int main(void) {
if (!glfwInit()) { exit(EXIT_FAILURE); }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(1500, 1200, "test", NULL, NULL);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
glfwSwapInterval(1);
glfwSetWindowSizeCallback(window, window_size_callback);
init(window);
while (!glfwWindowShouldClose(window)) {
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
fragShader.glsl
#version 430
in vec2 tc;
out vec4 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
layout (binding=0) uniform sampler2D s;
void main(void)
{ color = texture(s,tc);
}
vertShader.glsl
#version 430
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 tex_coord;
out vec2 tc;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
layout (binding=0) uniform sampler2D s;
void main(void)
{ gl_Position = proj_matrix * mv_matrix * vec4(position,1.0);
tc = tex_coord;
}
运行结果:
地球公转到太阳背面(相对于相机):
附纹理图片:
- earth.jpg
- sun.jpg
加入航天飞行器
main.cpp
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <SOIL2\soil2.h>
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <stack>
#include <glm\glm.hpp>
#include <glm\gtc\type_ptr.hpp> // glm::value_ptr
#include <glm\gtc\matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
#include "Utils.h"
#include "Sphere.h"
#include "ImportedModel.h"
using namespace std;
#define numVAOs 1
#define numVBOs 6
float cameraX, cameraY, cameraZ;
float sphLocX, sphLocY, sphLocZ;
float objLocX, objLocY, objLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];
GLuint earthTexture;
GLuint moonTexture;
GLuint sunTexture;
GLuint shuttleTexture;
float rotAmt = 0.0f;
// variable allocation for display
GLuint mvLoc, projLoc;
int width, height;
float aspect;
glm::mat4 pMat, vMat, mMat, mvMat;
ImportedModel myModel("shuttle.obj");
stack<glm::mat4> mvStack;
Sphere mySphere = Sphere(48);
float toRadians(float degrees) { return (degrees * 2.0f * 3.14159f) / 360.0f; }
void setupVertices(void) {
//球体
std::vector<int> ind = mySphere.getIndices();
std::vector<glm::vec3> vert = mySphere.getVertices();
std::vector<glm::vec2> tex = mySphere.getTexCoords();
std::vector<glm::vec3> norm = mySphere.getNormals();
std::vector<float> pvalues; //顶点位置
std::vector<float> tvalues; //纹理坐标
std::vector<float> nvalues; //法向量
int numIndices = mySphere.getNumIndices();
for (int i = 0; i < numIndices; i++) {
pvalues.push_back((vert[ind[i]]).x);
pvalues.push_back((vert[ind[i]]).y);
pvalues.push_back((vert[ind[i]]).z);
tvalues.push_back((tex[ind[i]]).s);
tvalues.push_back((tex[ind[i]]).t);
nvalues.push_back((norm[ind[i]]).x);
nvalues.push_back((norm[ind[i]]).y);
nvalues.push_back((norm[ind[i]]).z);
}
glGenVertexArrays(1, vao);
glBindVertexArray(vao[0]);
glGenBuffers(numVBOs, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, pvalues.size() * 4, &pvalues[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, tvalues.size() * 4, &tvalues[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ARRAY_BUFFER, nvalues.size() * 4, &nvalues[0], GL_STATIC_DRAW);
//航天器
std::vector<glm::vec3> vert1 = myModel.getVertices();
std::vector<glm::vec2> tex1 = myModel.getTextureCoords();
std::vector<glm::vec3> norm1 = myModel.getNormals();
std::vector<float> pvalues1;
std::vector<float> tvalues1;
std::vector<float> nvalues1;
for (int i = 0; i < myModel.getNumVertices(); i++) {
pvalues1.push_back((vert1[i]).x);
pvalues1.push_back((vert1[i]).y);
pvalues1.push_back((vert1[i]).z);
tvalues1.push_back((tex1[i]).s);
tvalues1.push_back((tex1[i]).t);
nvalues1.push_back((norm1[i]).x);
nvalues1.push_back((norm1[i]).y);
nvalues1.push_back((norm1[i]).z);
}
glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
glBufferData(GL_ARRAY_BUFFER, pvalues1.size() * 4, &pvalues1[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[4]);
glBufferData(GL_ARRAY_BUFFER, tvalues1.size() * 4, &tvalues1[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[5]);
glBufferData(GL_ARRAY_BUFFER, nvalues1.size() * 4, &nvalues1[0], GL_STATIC_DRAW);
}
void init(GLFWwindow* window) {
renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");
cameraX = 0.0f; cameraY = 0.0f; cameraZ = 2.0f;
sphLocX = 0.0f; sphLocY = 0.0f; sphLocZ = -1.0f;
objLocX = 0.0f; objLocY = 0.0f; objLocZ = 0.0f;
glfwGetFramebufferSize(window, &width, &height);
aspect = (float)width / (float)height;
pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
setupVertices();
sunTexture = Utils::loadTexture("sunmap.jpg");
earthTexture = Utils::loadTexture("earth.jpg");
moonTexture = Utils::loadTexture("moon.jpg");
shuttleTexture = Utils::loadTexture("spstob_1.jpg");
}
void display(GLFWwindow* window, double currentTime) {
glClear(GL_DEPTH_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(renderingProgram);
mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");
vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));
mvStack.push(vMat);
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
// ----------------------sun
mvStack.push(mvStack.top());
mvStack.top() *= glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
mvStack.push(mvStack.top());
mvStack.top() *= rotate(glm::mat4(1.0f), (float)currentTime, glm::vec3(0.0, 1.0, 0.0));
mvStack.top() *= scale(glm::mat4(1.0f), glm::vec3(0.25f, 0.25f, 0.25f));
glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvStack.top()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sunTexture);
glEnable(GL_CULL_FACE); //调整深度
glFrontFace(GL_CCW);
glDrawArrays(GL_TRIANGLES, 0, mySphere.getNumIndices());
mvStack.pop();
//-----------------------planet
mvStack.push(mvStack.top());
mvStack.top() *= glm::translate(glm::mat4(1.0f), glm::vec3(sin((float)currentTime)*1.0, 0.0f, cos((float)currentTime)*1.0));
mvStack.push(mvStack.top());
mvStack.top() *= rotate(glm::mat4(1.0f), (float)currentTime*3, glm::vec3(0.0, 1.0, 0.0));
mvStack.top() *= scale(glm::mat4(1.0f), glm::vec3(0.1f, 0.1f, 0.1f));
glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvStack.top()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, earthTexture);
glEnable(GL_CULL_FACE); //调整深度
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDrawArrays(GL_TRIANGLES, 0, mySphere.getNumIndices());
mvStack.pop();
//-----------------------moon
mvStack.push(mvStack.top());
mvStack.top() *= glm::translate(glm::mat4(1.0f), glm::vec3(sin((float)currentTime*7)*0.15, 0.0f, cos((float)currentTime*7)*0.15));
mvStack.top() *= rotate(glm::mat4(1.0f), (float)currentTime, glm::vec3(0.0, 0.0, 1.0));
mvStack.top() *= scale(glm::mat4(1.0f), glm::vec3(0.02f, 0.02f, 0.02f));
glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvStack.top()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, moonTexture);
glEnable(GL_CULL_FACE); //调整深度
glFrontFace(GL_CCW);
glDrawArrays(GL_TRIANGLES, 0, mySphere.getNumIndices());
mvStack.pop();
//-----------------------shuttle
mvStack.push(mvStack.top());
mvStack.top() *= glm::translate(glm::mat4(1.0f), glm::vec3(sin((float)currentTime)*0.3f, 0.0f, cos((float)currentTime) * 0.3f));
mvStack.push(mvStack.top());
mvStack.top() *= scale(glm::mat4(1.0f), glm::vec3(0.1f, 0.1f, 0.1f));
glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvStack.top()));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[4]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shuttleTexture);
glEnable(GL_CULL_FACE); //调整深度
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDrawArrays(GL_TRIANGLES, 0, myModel.getNumVertices());
mvStack.pop();
}
void window_size_callback(GLFWwindow* win, int newWidth, int newHeight) {
aspect = (float)newWidth / (float)newHeight;
glViewport(0, 0, newWidth, newHeight);
pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
}
int main(void) {
if (!glfwInit()) { exit(EXIT_FAILURE); }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(1500, 1200, "test", NULL, NULL);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
glfwSwapInterval(1);
glfwSetWindowSizeCallback(window, window_size_callback);
init(window);
while (!glfwWindowShouldClose(window)) {
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
运行结果: