- 来源:《Computer Graphics Programming in OpenGL Using C++ 》by V Scott Gordon John L Clevenger
- 内容:程序4.2 Instancing – Twenty-Four Animated Cubes,书P80页,PDF99/403
- 相关介绍可参考OpenGL–用一个立方体实例化为10万个立方体
- 这里参考了OpenGL–用一个立方体实例化为10万个立方体的 vertShader.glsl 和 fragShader.glsl 两份文件
结果,生成多个转动的彩色立方体,如下
生成24个立方体同时运动
- 文件1: 4.2 instancing.cpp
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include "glm\glm.hpp"
#include "glm\gtc\type_ptr.hpp"
#include "glm\gtc\matrix_transform.hpp"
#include "Utils\4.1 Utils.h"
using namespace std;
#define numVAOs 1
#define numVBOs 2
float cameraX, cameraY, cameraZ;
float cubeLocX, cubeLocY, cubeLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];
GLuint mvLoc, projLoc,vLoc,tfLoc;
int width, height;
float aspect, timeFactor;
glm::mat4 pMat, vMat, mMat, mvMat;
glm::mat4 tMat, rMat;
void setupVertices(void) {
float vertexPositions[108] = {
-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f
};
glGenVertexArrays(1, vao);
glBindVertexArray(vao[0]);
glGenBuffers(numVBOs, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
}
void init(GLFWwindow* window) {
renderingProgram = createShaderProgram("add/4.2 vertShader.glsl", "add/4.2 fragShader.glsl");
cameraX = 0.0f; cameraY = 0.0f; cameraZ = 32.0f;
setupVertices();
}
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);
vLoc = glGetUniformLocation(renderingProgram, "v_matrix");
projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");
vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));
glfwGetFramebufferSize(window, &width, &height);
aspect = (float)width / (float)height;
pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
glUniformMatrix4fv(vLoc, 1, GL_FALSE, glm::value_ptr(vMat));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
timeFactor = ((float)currentTime);
tfLoc = glGetUniformLocation(renderingProgram, "tf");
glUniform1f(tfLoc, (float)timeFactor);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 24);
}
int main(void) {
if (!glfwInit()) { exit(EXIT_FAILURE); }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(600, 600, "Chapter 4 - program 1", NULL, NULL);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
glfwSwapInterval(1);
init(window);
while (!glfwWindowShouldClose(window)) {
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
- 文件2: 4.2 vertShader.glsl 参考OpenGL–用一个立方体实例化为10万个立方体的即可运行
#version 430
layout (location=0) in vec3 position;
uniform mat4 v_matrix;
uniform mat4 proj_matrix;
uniform float tf;
out vec4 varyingColor;
mat4 buildRotateX(float rad);
mat4 buildRotateY(float rad);
mat4 buildRotateZ(float rad);
mat4 buildTranslate(float x,float y,float z);
void main(void)
{
float i=gl_InstanceID+tf;
float a=sin(0.35*i)*8.0;
float b=sin(0.52*i)*8.0;
float c=sin(0.70*i)*8.0;
mat4 localRotX=buildRotateX(0.1*i);
mat4 localRotY=buildRotateY(0.1*i);
mat4 localRotZ=buildRotateZ(0.1*i);
mat4 localTrans=buildTranslate(a,b,c);
mat4 newM_matrix=localTrans*localRotX*localRotY*localRotZ;
mat4 mv_matrix=v_matrix*newM_matrix;
gl_Position = proj_matrix * mv_matrix * vec4(position,1.0);
varyingColor = vec4(position,1.0)*0.5+vec4(0.5,0.5,0.5,0.5);
}
mat4 buildTranslate(float x,float y,float z)
{
mat4 trans=mat4(1.0,0.0,0.0,0.0,
0.0,1.0,0.0,0.0,
0.0,0.0,1.0,0.0,
x,y,z,1.0);
return trans;
}
mat4 buildRotateX(float rad)
{
mat4 trans=mat4(
1.0,0.0,0.0,0.0,
0.0,cos(rad),-sin(rad),0.0,
0.0,sin(rad),cos(rad),0.0,
0.0,0.0,0.0,1.0);
return trans;
}
mat4 buildRotateY(float rad)
{
mat4 trans=mat4(
cos(rad),0.0,sin(rad),0.0,
0.0,1.0,0.0,0.0,
-sin(rad),0.0,cos(rad),0.0,
0.0,0.0,0.0,1.0);
return trans;
}
mat4 buildRotateZ(float rad)
{
mat4 trans=mat4(
cos(rad),sin(rad),0.0,0.0,
-sin(rad),cos(rad),0.0,0.0,
0.0,0.0,1.0,0.0,
0.0,0.0,0.0,1.0);
return trans;
}
3. 文件2: 4.2 fragShader.glsl 参考[OpenGL--用一个立方体实例化为10万个立方体](https:
```cpp
#version 430
in vec4 varyingColor;
out vec4 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
void main(void)
{ color = varyingColor;
}
生成10万个立方体同时运动
- 文件1: 4.2 instancing.cpp
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include "glm\glm.hpp"
#include "glm\gtc\type_ptr.hpp"
#include "glm\gtc\matrix_transform.hpp"
#include "Utils\4.1 Utils.h"
using namespace std;
#define numVAOs 1
#define numVBOs 2
float cameraX, cameraY, cameraZ;
float cubeLocX, cubeLocY, cubeLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];
GLuint mvLoc, projLoc,vLoc,tfLoc;
int width, height;
float aspect, timeFactor;
glm::mat4 pMat, vMat, mMat, mvMat;
glm::mat4 tMat, rMat;
void setupVertices(void) {
float vertexPositions[108] = {
-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f
};
glGenVertexArrays(1, vao);
glBindVertexArray(vao[0]);
glGenBuffers(numVBOs, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
}
void init(GLFWwindow* window) {
renderingProgram = createShaderProgram("add/4.2 vertShader.glsl", "add/4.2 fragShader.glsl");
cameraX = 0.0f; cameraY = 0.0f; cameraZ = 420.0f;
setupVertices();
}
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);
vLoc = glGetUniformLocation(renderingProgram, "v_matrix");
projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");
vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));
glfwGetFramebufferSize(window, &width, &height);
aspect = (float)width / (float)height;
pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
glUniformMatrix4fv(vLoc, 1, GL_FALSE, glm::value_ptr(vMat));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
timeFactor = ((float)currentTime);
tfLoc = glGetUniformLocation(renderingProgram, "tf");
glUniform1f(tfLoc, (float)timeFactor);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 100000);
}
int main(void) {
if (!glfwInit()) { exit(EXIT_FAILURE); }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(600, 600, "Chapter 4 - program 1", NULL, NULL);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
glfwSwapInterval(1);
init(window);
while (!glfwWindowShouldClose(window)) {
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
- 文件2: 4.2 vertShader.glsl 参考OpenGL–用一个立方体实例化为10万个立方体的即可运行
#version 430
layout (location=0) in vec3 position;
uniform mat4 v_matrix;
uniform mat4 proj_matrix;
uniform float tf;
out vec4 varyingColor;
mat4 buildRotateX(float rad);
mat4 buildRotateY(float rad);
mat4 buildRotateZ(float rad);
mat4 buildTranslate(float x,float y,float z);
void main(void)
{
float i=gl_InstanceID+tf;
float a=sin(203.0*i/8000.0)*403.0;
float b=sin(301.0*i/4001.0)*401.0;
float c=sin(400.0*i/6003.0)*405.0;
mat4 localRotX=buildRotateX(0.1*i);
mat4 localRotY=buildRotateY(0.1*i);
mat4 localRotZ=buildRotateZ(0.1*i);
mat4 localTrans=buildTranslate(a,b,c);
mat4 newM_matrix=localTrans*localRotX*localRotY*localRotZ;
mat4 mv_matrix=v_matrix*newM_matrix;
gl_Position = proj_matrix * mv_matrix * vec4(position,1.0);
varyingColor = vec4(position,1.0)*0.5+vec4(0.5,0.5,0.5,0.5);
}
mat4 buildTranslate(float x,float y,float z)
{
mat4 trans=mat4(1.0,0.0,0.0,0.0,
0.0,1.0,0.0,0.0,
0.0,0.0,1.0,0.0,
x,y,z,1.0);
return trans;
}
mat4 buildRotateX(float rad)
{
mat4 trans=mat4(
1.0,0.0,0.0,0.0,
0.0,cos(rad),-sin(rad),0.0,
0.0,sin(rad),cos(rad),0.0,
0.0,0.0,0.0,1.0);
return trans;
}
mat4 buildRotateY(float rad)
{
mat4 trans=mat4(
cos(rad),0.0,sin(rad),0.0,
0.0,1.0,0.0,0.0,
-sin(rad),0.0,cos(rad),0.0,
0.0,0.0,0.0,1.0);
return trans;
}
mat4 buildRotateZ(float rad)
{
mat4 trans=mat4(
cos(rad),sin(rad),0.0,0.0,
-sin(rad),cos(rad),0.0,0.0,
0.0,0.0,1.0,0.0,
0.0,0.0,0.0,1.0);
return trans;
}
- 文件2: 4.2 fragShader.glsl 参考OpenGL–用一个立方体实例化为10万个立方体的即可运行 (与生成24个立方体的相同,无需修改)
#version 430
in vec4 varyingColor;
out vec4 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
void main(void)
{ color = varyingColor;
}
改变立方体的数量,需要更改的部分
-
4.2 instancing.cpp中,主要改两个地方 init 函数: cameraX = 0.0f; cameraY = 0.0f; cameraZ = 32.0f; //24个立方体时对应z=32 cameraX = 0.0f; cameraY = 0.0f; cameraZ = 420.0f; //10万个立方体时对应z=420 display 函数: glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 24); // 24个立方体, glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 100000); // 10万个立方体 -
4.2 vertShader.glsl 如果是10万个立方体: //float a=sin(0.35*i)8.0; //这些是用来平移的x,y,z分量,24个的时候 //float b=sin(0.52i)8.0; //float c=sin(0.70i)*8.0;
float a=sin(203.0*i/8000.0)*403.0; //这些是用来平移的x,y,z分量
float b=sin(301.0*i/4001.0)*401.0;
float c=sin(400.0*i/6003.0)*405.0;
如果是24个立方体: float a=sin(0.35*i)8.0; //这些是用来平移的x,y,z分量,24个的时候 float b=sin(0.52i)8.0; float c=sin(0.70i)*8.0;
//float a=sin(203.0*i/8000.0)*403.0; //这些是用来平移的x,y,z分量
//float b=sin(301.0*i/4001.0)*401.0;
//float c=sin(400.0*i/6003.0)*405.0;
- 4.2 fragShader.glsl文件中不需要更改
|