Shader 渲染粒子
我正在尝试创建一个粒子系统。我正在使用转换反馈,现在我只是想让它在一点上起作用。问题在于,绘制循环的每次迭代都会渲染多个点。尽管我的粒子缓冲区只能容纳一个点,但点似乎一直在增加。循环不是绘制一个然后移动的点,而是为每次迭代添加一个点。下面是程序的代码,然后是顶点着色器的代码。此时我不使用任何几何体着色器Shader 渲染粒子,shader,vertex-buffer,particle-system,transform-feedback,Shader,Vertex Buffer,Particle System,Transform Feedback,我正在尝试创建一个粒子系统。我正在使用转换反馈,现在我只是想让它在一点上起作用。问题在于,绘制循环的每次迭代都会渲染多个点。尽管我的粒子缓冲区只能容纳一个点,但点似乎一直在增加。循环不是绘制一个然后移动的点,而是为每次迭代添加一个点。下面是程序的代码,然后是顶点着色器的代码。此时我不使用任何几何体着色器 #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include "Dependencies/glew/glew.h"
#include "Dependencies/glut/glut.h"
#include <time.h>
#include <iostream>
#include <sys/stat.h>
#include "Dependencies/glm/glm.hpp"
using namespace glm;
struct Particles{
vec3 Position = vec3(0.0, 0.0, 0.0);
//vec3 Velocity = vec3(0.0, 0.0, 0.0);
};
GLint inputAttrib;
GLuint program, programFrag, drawProgram; //Program object for using shaders above
GLuint m_TFB[2], m_PB[2]; //two transfromfbs and 2 pbuffers
GLuint query; //Keep track of amount of objects
unsigned int m_currVB;
unsigned int m_currTFB;
bool first = true;
const static int MAX_NUMBER = 1;
char* readShaderFile(const char *filename) {
FILE *file;
struct stat st;
file = fopen(filename, "r");
if (file == NULL){
fprintf(stderr, "ERROR: Cannot open shader file!");
return 0;
}
stat(filename, &st);
int bytesinfile = st.st_size;
char *buffer = (char*)malloc(bytesinfile + sizeof(char));
int bytesread = fread(buffer, 1, bytesinfile, file);
buffer[bytesread] = 0; // Terminate the string with 0
fclose(file);
return buffer;
}
void loadShaders(){
//load our vertex shader
GLint vertShader = glCreateShader(GL_VERTEX_SHADER);
const char *vertexAssembly = readShaderFile("vertex_shader.vert");
glShaderSource(vertShader, 1, &vertexAssembly, NULL);
glCompileShader(vertShader);
free((void *)vertexAssembly);
GLint isCompiled;
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
char str[256];
glGetShaderInfoLog(vertShader, 256, NULL, str);
fprintf(stderr, "Vertex shader compile error: %s\n", str);
}
program = glCreateProgram();
glAttachShader(program, vertShader);
const GLchar* feedbackVaryings[1];
feedbackVaryings[0] = "Position0";
//feedbackVaryings[1] = "Velocity0";
glTransformFeedbackVaryings(program, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(program);
//load our vertex draw shader
GLint vertDraw = glCreateShader(GL_VERTEX_SHADER);
const char *drawVertAssembly = readShaderFile("draw.vert");
glShaderSource(vertDraw, 1, &drawVertAssembly, NULL);
glCompileShader(vertDraw);
free((void *)drawVertAssembly);
glGetShaderiv(vertDraw, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
char str[256];
glGetShaderInfoLog(vertDraw, 256, NULL, str);
fprintf(stderr, "Vertex draw shader compile error: %s\n", str);
}
else{
std::cout << "Vert draw ok!" << std::endl;
}
drawProgram = glCreateProgram();
glAttachShader(drawProgram, vertDraw);
//load our vertex shader
GLint fragDraw = glCreateShader(GL_FRAGMENT_SHADER);
const char *drawFragAssembly = readShaderFile("draw.frag");
glShaderSource(fragDraw, 1, &drawFragAssembly, NULL);
glCompileShader(fragDraw);
free((void *)drawFragAssembly);
glGetShaderiv(fragDraw, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
char str[256];
glGetShaderInfoLog(fragDraw, 256, NULL, str);
fprintf(stderr, "Fragment draw shader compile error: %s\n", str);
}
else{
std::cout << "Frag draw ok!" << std::endl;
}
glAttachShader(drawProgram, fragDraw);
glLinkProgram(drawProgram);
}
void initSystem(){
loadShaders();
Particles data[MAX_NUMBER];
data[0].Position = vec3(0.0, 0.0, 0.0);
//data[0].Velocity = vec3(0.1, 0.0, 0.0);
glGenTransformFeedbacks(2, m_TFB);
glGenBuffers(2, m_PB);
for (int i = 0; i < 2; i++){
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_TFB[i]);
glBindBuffer(GL_ARRAY_BUFFER, m_PB[i]);
//glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GL_FLOAT), data, GL_STREAM_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(vec3), &data[0], GL_DYNAMIC_DRAW);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_PB[i]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
void updateParticles(){
glClear(GL_COLOR_BUFFER_BIT || GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//Don't draw anything yet
glEnable(GL_RASTERIZER_DISCARD);
//Bind particle buffer to write from
glBindBuffer(GL_ARRAY_BUFFER, m_PB[m_currVB]);
//Create our attribute pointer. We only have position in the loop. The array is tightly packed maybe? We want to start drawing from the beginning?
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Particles), (GLvoid*)0);
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (const GLvoid*)(3 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
//Bind transform buffer to write to
//glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_TFB[m_currTFB]);
//Begin transformfeedback here we go man!!
//Use our shaders for updating
glUseProgram(program);
glBeginTransformFeedback(GL_POINTS);
glPointSize(20.0f);
if (first){
glDrawArrays(GL_POINTS, 0, 1);
first = false;
}
else{
glDrawTransformFeedback(GL_POINTS, m_TFB[m_currVB]);
}
glEndTransformFeedback();
glUseProgram(0);
//Disable dose arrays
glDisableVertexAttribArray(0);
//glDisableVertexAttribArray(1);
//Unbind our buffer to end this part of the operation
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
}
void drawParticles(){
//Now we want to actually draw some shit on the screen
glDisable(GL_RASTERIZER_DISCARD);
//Use our program for rendering
glUseProgram(drawProgram);
glClear(GL_COLOR_BUFFER_BIT || GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//Bind particle buffer to draw points retrived from this draw call
glBindBuffer(GL_ARRAY_BUFFER, m_PB[m_currTFB]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Particles), (GLvoid*)0);
glEnableVertexAttribArray(0);
//Draw as many points as we have got in this draw call
glDrawTransformFeedback(GL_POINTS, m_TFB[m_currVB]);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
glutSwapBuffers();
}
void render(){
updateParticles();
drawParticles();
/*unsigned int tmp;
tmp = m_currTFB;
m_currTFB = m_currVB;
m_currVB = tmp;*/
m_currVB = m_currTFB;
m_currTFB = (m_currTFB + 1) & 0x1;
}
void init(){
glEnable(GL_DEPTH_TEST);
srand(time(NULL));
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutCreateWindow("ShaderTest");
glutInitWindowPosition(100, 100);
printf("%s\n", glGetString(GL_VERSION));
glewInit();
if (glewIsSupported("GL_VERSION_4_3"))
{
std::cout << " GLEW Version is 4.3\n ";
}
else
{
std::cout << "GLEW 4.3 not supported\n ";
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
init();
initSystem();
glutDisplayFunc(render);
glutIdleFunc(idle);
glutReshapeFunc(reshape);
glutMainLoop();
}
Below is the code for my vertex shader
#version 330
layout (location = 0) in vec3 Position;
layout (location = 0) out vec3 Position0;
void main() {
Position0 = Position + vec3(0.1,0.1,0.0);// + Velocity;
//Velocity0 = Velocity;
}
Furthermore I use a separate vertex shader and fragment shader for rendering the points.
#version 330
layout (location = 0) in vec3 Position;
out vec4 gl_Position;
void main() {
gl_Position.xyz = Position;
gl_Position.w = 1;
}
#version 330
out vec4 frag_color;
void main() {
frag_color = vec4(1,0,0,1);
}
#包括“stdafx.h”
#包括
#包括
#包括“依赖项/glew/glew.h”
#包括“依赖项/glut/glut.h”
#包括
#包括
#包括
#包括“依赖项/glm/glm.hpp”
使用名称空间glm;
结构粒子{
vec3位置=vec3(0.0,0.0,0.0);
//vec3速度=vec3(0.0,0.0,0.0);
};
闪烁输入;
GLuint程序、programFrag程序、drawProgram程序//用于使用上述着色器的程序对象
GLuint m_TFB[2],m_PB[2]//两个Transfromfb和两个PBuffer
GLuint查询//跟踪对象的数量
无符号整数m_currVB;
无符号整数m_currTFB;
bool first=true;
const static int MAX_NUMBER=1;
char*readShaderFile(常量char*filename){
文件*文件;
结构统计;
file=fopen(文件名为“r”);
if(file==NULL){
fprintf(stderr,“错误:无法打开着色器文件!”);
返回0;
}
stat(文件名,&st);
int bytesinfle=标准标准尺寸;
char*buffer=(char*)malloc(bytesinfle+sizeof(char));
int bytesread=fread(缓冲区,1,bytesinfile,文件);
buffer[bytesread]=0;//用0终止字符串
fclose(文件);
返回缓冲区;
}
void loader着色器(){
//加载我们的顶点着色器
闪烁顶点着色器=glCreateShader(GLU顶点着色器);
const char*vertexAssembly=readShaderFile(“vertex_shader.vert”);
glShaderSource(vertShader,1和vertexAssembly,NULL);
glCompileShader(vertShader);
自由((空*)顶点组件);
闪闪发光;
glGetShaderiv(顶点着色器、GL\u编译状态和isCompiled);
如果(isCompiled==GL_FALSE)
{
char-str[256];
glGetShaderInfoLog(vertShader,256,NULL,str);
fprintf(stderr,“顶点着色器编译错误:%s\n”,str);
}
program=glCreateProgram();
glAttachShader(程序、顶点着色器);
const GLchar*反馈变量[1];
反馈变量[0]=“位置0”;
//反馈变量[1]=“速度0”;
glTransformFeedbackVaryings(程序,1,反馈变量,GLU交错属性);
glLinkProgram(program);
//加载顶点绘制着色器
闪烁顶点绘制=glCreateShader(GL_顶点_着色器);
const char*drawVertAssembly=readShaderFile(“draw.vert”);
glShaderSource(vertDraw,1和drawVertAssembly,NULL);
glCompileShader(vertDraw);
自由((空*)组件);
glGetShaderiv(垂直绘制、GL编译状态和isCompiled);
如果(isCompiled==GL_FALSE)
{
char-str[256];
glGetShaderInfoLog(vertDraw,256,NULL,str);
fprintf(stderr,“顶点绘制着色器编译错误:%s\n”,str);
}
否则{
std::cout我自己设法解决了它。行“glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);”是错误的,应该是“glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);”如果这对我有帮助的话,我发现12的粒子大小不匹配(m_PB[m_currTFB])也就是4。但可能是我不明白顶点指针是怎么工作的。