我试图实现一个程序,根据按键将一个立方体变成一个球体,并在它被点击时发出涟漪声。我设法实现了立方体到球体和背部的部分,但我完全不知道从哪里开始涟漪。我在网上查看了大量的资料,我得到了数学,但我不知道如何在我的顶点着色器上实现它。任何人都可以帮我解决我的困境吗?谢谢!
这是我的cpp,vsh和fsh:https://drive.google.com/file/d/0B4hkcF9foOTgbUozMjZmSHJhQWM/view?usp=sharing
我使用的是GLSL,OpenGL 4.4.0
这是我的顶点着色器代码:
#version 120
attribute vec3 pos;
varying vec4 out_color;
uniform float t;
float PI = 3.14159265357;
int factor = 2; //for determining colors
int num_colors; // = factor * 3 (because RGB)
float currang = 0;
float angfac;
vec4 calculate( float a )
{
//this is just to calculate for the color
}
void main() {
num_colors = factor*3;
angfac = 2*PI/num_colors;
float ang = atan( pos.z, pos.x )+PI;
out_color = calculate(ang);
//rotation
mat3 rotateX = mat3(
vec3( 1, 0, 0),
vec3( 0, cos(t), sin(t)),
vec3( 0, -sin(t), cos(t))
);
mat3 rotateY = mat3(
vec3( cos(t), 0, -sin(t)),
vec3( 0, 1, 0),
vec3( sin(t), 0, cos(t))
);
mat3 rotateZ = mat3(
vec3( cos(t), sin(t), 0),
vec3(-sin(t), cos(t), 0),
vec3( 0, 0, cos(t))
);
gl_Position = gl_ModelViewProjectionMatrix * vec4((pos.xyz*rotateY*rotateX) , 1.0 );
}
以及我的cpp文件的部分内容:
//usual include statements
using namespace std;
enum { ATTRIB_POS };
GLuint mainProgram = 0;
// I use this to indicate the position of the vertices
struct Vtx {
GLfloat x, y, z;
};
const GLfloat PI = 3.14159265357;
const int sideLength = 10;
const size_t nVertices = (sideLength*sideLength*sideLength)-((sideLength-2)*(sideLength-2)*(sideLength-2));
Vtx cube[nVertices];
Vtx sphere[nVertices];
Vtx diff[nVertices];
const double TIME_SPEED = 0.01;
int mI = 4*(sideLength-1);
const int sLCubed = sideLength*sideLength*sideLength;
int indices[nVertices*nVertices];
GLfloat originX = 0.0f; //offset
GLfloat originY = 0.0f; //offset
bool loadShaderSource(GLuint shader, const char *path) {...}
void checkShaderStatus(GLuint shader) {...}
bool initShader() {...}
//in this part of the code, I instantiate an array of indices to be used by glDrawElements()
void transform(int fac)
{
//move from cube to sphere and back by adding/subtracting values and updating cube[].xyz
//moveSpeed = diff[]/speedFac
//fac is to determine direction (going to sphere or going to cube; going to sphere is plus, going back to cube is minus)
for( int i = 0; i<nVertices; i++ )
{
cube[i].x += fac*diff[i].x;
cube[i].y += fac*diff[i].y;
cube[i].z += fac*diff[i].z;
}
}
void initCube() {...} //computation for the vertices of the cube depending on sideLength
void initSphere() {...} //computation for the vertices of the sphere based on the vertices of the cube
void toSphere() {...} //changes the values of the array of vertices of the cube to those of the sphere
void initDiff() {...} //computes for the difference of the values of the vertices of the sphere and the vertices of the cube for the slow transformation
int main() {
//error checking (GLEW, OpenGL versions, etc)
glfwSetWindowTitle("CS177 Final Project");
glfwEnable( GLFW_STICKY_KEYS );
glfwSwapInterval( 1 );
glClearColor(0,0,0,0);
if ( !initShader() ) {
return -1;
}
glEnableVertexAttribArray(ATTRIB_POS);
glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(Vtx), cube);
initCube();
initIndices();
initSphere();
initDiff();
glUseProgram(mainProgram);
GLuint UNIF_T = glGetUniformLocation(mainProgram, "t");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float t = 0;
glUniform1f(UNIF_T, t);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glPointSize(2.0);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glfwOpenWindowHint(GLFW_FSAA_SAMPLES,16);
glEnable(GL_MULTISAMPLE);
do {
int width, height;
glfwGetWindowSize( &width, &height );
glViewport( 0, 0, width, height );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
t += TIME_SPEED;
glUniform1f(UNIF_T, t);
if (glfwGetKey(GLFW_KEY_DEL)) transform(-1);
if (glfwGetKey(GLFW_KEY_INSERT)) transform( 1 );
if (glfwGetKey(GLFW_KEY_HOME)) initCube();
if (glfwGetKey(GLFW_KEY_END)) toSphere();
glDrawElements( GL_TRIANGLES, nVertices*nVertices, GL_UNSIGNED_INT, indices);
glfwSwapBuffers();
} while ( glfwGetKey(GLFW_KEY_ESC) != GLFW_PRESS &&
glfwGetWindowParam(GLFW_OPENED) );
glDeleteProgram(mainProgram);
glfwTerminate();
return 0;
}