/*! \internal Construct a new QGLSection on the display list \a list, and with smoothing \a s. By default the smoothing is QGL::Smooth. See QGLBuilder for a discussion of smoothing. The pointer \a list must be non-null, and in debug mode, unless QT_NO_DEBUG is defined, this function will assert if \a list is null. The following lines of code have identical effect: \code QGLSection *s = myDisplayList->newSection(QGL::Faceted); QGLSection *s2 = new QGLSection(myDisplayList, QGL::Faceted); \endcode */ QGLSection::QGLSection(QGLBuilder *list, QGL::Smoothing s) : m_smoothing(s) , m_displayList(list) , d(0) { Q_ASSERT(m_displayList); enableField(QGL::Position); Q_ASSERT(vertexData()); d = new QGLSectionPrivate(vertexData()); m_displayList->addSection(this); }
void Quads::uploadVertices() const { glBindBuffer(GL_ARRAY_BUFFER, vertexAndTextureBuf); glBufferData( GL_ARRAY_BUFFER, vertexDataByteCount(), vertexData(), GL_STATIC_DRAW); }
Mesh* CreateSolidPlane(float xSize, float zSize, int xSegments, int zSegments, const glm::mat4& transform) { int numVertices = (xSegments + 1) * (zSegments + 1); std::vector<VertexPositionNormal> vertexData(numVertices); float xStep = xSize / xSegments; float zStep = zSize / zSegments; VertexPositionNormal* vertexPtr = &vertexData[0]; float z = -0.5f * zSize; for (int j = 0; j <= zSegments; j++) { float x = -0.5f * xSize; for (int i = 0; i <= xSegments; i++) { vertexPtr->pos.x = x; vertexPtr->pos.y = 0; vertexPtr->pos.z = z; vertexPtr->normal.x = 0; vertexPtr->normal.y = 1; vertexPtr->normal.z = 0; ++vertexPtr; x += xStep; } z += zStep; } int numTriangles = 2 * xSegments * zSegments; int numElements = 3 * numTriangles; std::vector<unsigned> indexData(numElements); // use 32-bit indices for large planes!!!11!!! unsigned* indexPtr = &indexData[0]; unsigned e = 0; for (int j = 0; j < zSegments; j++) { for (int i = 0; i < xSegments; i++) { // the four corners of this "square" unsigned e = (xSegments + 1) * j + i; unsigned e1 = e; unsigned e2 = e + 1; unsigned e3 = e + xSegments + 1; unsigned e4 = e + xSegments + 2; // triangle 1 *indexPtr++ = e1; *indexPtr++ = e3; *indexPtr++ = e4; // triangle 2 *indexPtr++ = e1; *indexPtr++ = e4; *indexPtr++ = e2; ++e; } ++e; } return CreateMesh(GL_TRIANGLES, vertexData, indexData); }
void BindlingLoopsGeometry::addExpandedEvent(float itemCenter) { float verticalCenter = Timeline::TimelineModel::defaultRowHeight() / 2.0; Point2DWithOffset *v = vertexData() + usedVertices; v[0].set(itemCenter, verticalCenter, -1.0f, currentY); v[1].set(itemCenter, verticalCenter, +1.0f, currentY); currentY = -currentY; v[2].set(itemCenter, verticalCenter, -1.0f, currentY); v[3].set(itemCenter, verticalCenter, +1.0f, currentY); usedVertices += 4; }
std::shared_ptr<MeshData>& ResourceManager::makeMesh(const std::string& name) { if (this->meshDataCache.find(name) == this->meshDataCache.end()) { Logger::getInstance().log(Logger::LOG_INFO, "Loading mesh `%s'", name.c_str()); std::shared_ptr<MeshData> vertexData(new MeshData()); if (!vertexData->load(name)) { // VertexData::load() prints errors for us return this->meshDataCache["nullptr"]; } this->meshDataCache.insert(std::make_pair(name, vertexData)); } return this->meshDataCache[name]; }
void PCPRenderer::invalidateBuffer() { if (!_inport.hasData()) return; std::shared_ptr<const ParallelCoordinatesPlotData> data = _inport.getData(); if (_dimensionOrdering.empty()) { _dimensionOrdering.resize(data->nDimensions); std::iota(_dimensionOrdering.begin(), _dimensionOrdering.end(), 0); } if (_dimensionOrdering.size() != data->nDimensions) { LogError("Wrong dimensions. Dimension ordering: " << _dimensionOrdering.size() << " nDimensions: " << data->nDimensions ); return; } glBindBuffer(GL_ARRAY_BUFFER, _vbo); std::vector<float> vertexData(data->nDimensions); for (int i = 0; i < data->nDimensions; ++i) vertexData[i] = dimensionLocation(i, _horizontalBorder, data->nDimensions); //int dim = _dimensionOrdering[i]; glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(float), vertexData.data(), GL_DYNAMIC_DRAW ); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_SHADER_STORAGE_BUFFER, _dimensionOrderingBuffer); glBufferData( GL_SHADER_STORAGE_BUFFER, _dimensionOrdering.size() * sizeof(int), _dimensionOrdering.data(), GL_STATIC_DRAW ); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); }
shared_ptr<VertexBuffer> createQuad2(const VertexFormat &vf, float x, float y, float w, float h, GpuBufferUsageType usage) { // TODO_REFACTO remove this shit!!! float w2 = w / 2.0f; float h2 = h / 2.0f; float quad_pos[][2] = { { x - w2, y - h2 }, { x + w2, y - h2 }, { x + w2, y + h2 }, { x + w2, y + h2 }, { x - w2, y + h2 }, { x - w2, y - h2 } }; float quad_uv[][2] = { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 0.0, 1.0 }, { 0.0, 0.0 } }; VertexData vertexData(vf); for (int i = 0; i < 6; i++) { auto v = vertexData.allocVertex(); v.setPosition({ quad_pos[i][0], quad_pos[i][1], 0.0f }); v.setTx({ quad_uv[i][0], quad_uv[i][1] }); v.setColor({ 1.0f, 1.0f, 1.0f, 1.0f }); } auto result = make_shared<VertexBuffer>(vf); result->alloc(vertexData, usage); return result; }
std::shared_ptr<Geom> TriSoup::CreateGeom(const TriSoup& soup) { std::vector<IndexType> indices(3 * soup.NumFaces()); std::vector<float> vertexData(6 * soup.NumVertices()); const int vtxStride = 6 * sizeof(float); unsigned int offset = 0; const unsigned int numVertices = Min<unsigned int>(soup.m_vertices.size(), std::numeric_limits<IndexType>::max()); for(unsigned int i = 0; i < numVertices; ++i) { const auto& vtx = soup.m_vertices[i]; vertexData[offset++] = vtx.m_pos.x; vertexData[offset++] = vtx.m_pos.y; vertexData[offset++] = vtx.m_pos.z; vertexData[offset++] = vtx.m_normal.x; vertexData[offset++] = vtx.m_normal.y; vertexData[offset++] = vtx.m_normal.z; } offset = 0; for(const auto& face: soup.m_faces) { if(std::any_of(face.m_vertices, face.m_vertices+3, [](int val) { return (unsigned int)val > std::numeric_limits<IndexType>::max(); })) continue; indices[offset++] = face.m_vertices[0]; indices[offset++] = face.m_vertices[1]; indices[offset++] = face.m_vertices[2]; } const unsigned int numIndices = offset; return std::make_shared<Geom>( numVertices, &vertexData[0], numIndices, &indices[0], vtxStride, GL_TRIANGLES, std::vector<GeomBindPair>{ {GEOM_Pos, 3, 0}, {GEOM_Normal, 3, 3 * sizeof(float)}, }); }
Quad::Quad(RenderDevice* renderDevice) : Mesh(renderDevice) { VertexFloat verticeArray[] = { VertexFloat(-1.0f, 1.0f, 0.0f, 0.0, 0.0, 1.0, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), VertexFloat(-1.0f, -1.0f, 0.0f, 0.0, 0.0, 1.0, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f), VertexFloat(1.0f, -1.0f, 0.0f, 0.0, 0.0, 1.0, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f), VertexFloat(1.0f, 1.0f, 0.0f, 0.0, 0.0, 1.0, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f) }; std::vector<VertexFloat> vertexData(verticeArray, verticeArray + sizeof(verticeArray) / sizeof(verticeArray[0])); unsigned int indexArray[] = { 0, 1, 2, 0, 2, 3, }; std::vector<unsigned int> indexData(indexArray, indexArray + sizeof(indexArray) / sizeof(indexArray[0])); m_Buffer->setVertices(vertexData.size(), &vertexData[0]); m_Buffer->setIndices(indexData.size(), &indexData[0]); }
void BindlingLoopsGeometry::addCollapsedEvent(float horizontalCenterSource, float horizontalCenterTarget, float verticalCenterSource, float verticalCenterTarget) { if (verticalCenterSource < verticalCenterTarget) { qSwap(verticalCenterSource, verticalCenterTarget); qSwap(horizontalCenterSource, horizontalCenterTarget); } float tilt = horizontalCenterSource < horizontalCenterTarget ? +0.3 : -0.3; Point2DWithOffset *v = vertexData() + usedVertices; v[0].set(horizontalCenterSource, verticalCenterSource, -0.3f, tilt); v[1].set(horizontalCenterSource, verticalCenterSource, -0.3f, tilt); v[2].set(horizontalCenterSource, verticalCenterSource, +0.3f, -tilt); v[3].set(horizontalCenterTarget, verticalCenterTarget, -0.3f, tilt); v[4].set(horizontalCenterTarget, verticalCenterTarget, +0.3f, -tilt); v[5].set(horizontalCenterTarget, verticalCenterTarget, -1.0f, -1.0f); v[6].set(horizontalCenterTarget, verticalCenterTarget, +1.0f, -1.0f); v[7].set(horizontalCenterTarget, verticalCenterTarget, -1.0f, +1.0f); v[8].set(horizontalCenterTarget, verticalCenterTarget, +1.0f, +1.0f); v[9].set(horizontalCenterTarget, verticalCenterTarget, -0.3f, tilt); v[10].set(horizontalCenterTarget, verticalCenterTarget, +0.3f, -tilt); v[11].set(horizontalCenterSource, verticalCenterSource, -0.3f, tilt); v[12].set(horizontalCenterSource, verticalCenterSource, +0.3f, -tilt); v[13].set(horizontalCenterSource, verticalCenterSource, -1.0f, +1.0f); v[14].set(horizontalCenterSource, verticalCenterSource, +1.0f, +1.0f); v[15].set(horizontalCenterSource, verticalCenterSource, -1.0f, -1.0f); v[16].set(horizontalCenterSource, verticalCenterSource, +1.0f, -1.0f); v[17].set(horizontalCenterSource, verticalCenterSource, +1.0f, -1.0f); usedVertices += 18; }
void btSoftBodySolverOutputCLtoGL::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) { btSoftBodySolver *solver = softBody->getSoftBodySolver(); btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER ); btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver ); checkInitialized(); btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody ); btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData ); const int firstVertex = currentCloth->getFirstVertex(); const int lastVertex = firstVertex + currentCloth->getNumVertices(); if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::OPENGL_BUFFER ) { const btOpenGLInteropVertexBufferDescriptor *openGLVertexBuffer = static_cast< btOpenGLInteropVertexBufferDescriptor* >(vertexBuffer); cl_int ciErrNum = CL_SUCCESS; cl_mem clBuffer = openGLVertexBuffer->getBuffer(); cl_kernel outputKernel = outputToVertexArrayWithNormalsKernel; if( !vertexBuffer->hasNormals() ) outputKernel = outputToVertexArrayWithoutNormalsKernel; ciErrNum = clEnqueueAcquireGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, NULL); if( ciErrNum != CL_SUCCESS ) { btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); } int numVertices = currentCloth->getNumVertices(); ciErrNum = clSetKernelArg(outputKernel, 0, sizeof(int), &firstVertex ); ciErrNum = clSetKernelArg(outputKernel, 1, sizeof(int), &numVertices ); ciErrNum = clSetKernelArg(outputKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); if( vertexBuffer->hasVertexPositions() ) { int vertexOffset = vertexBuffer->getVertexOffset(); int vertexStride = vertexBuffer->getVertexStride(); ciErrNum = clSetKernelArg(outputKernel, 3, sizeof(int), &vertexOffset ); ciErrNum = clSetKernelArg(outputKernel, 4, sizeof(int), &vertexStride ); ciErrNum = clSetKernelArg(outputKernel, 5, sizeof(cl_mem), (void*)&vertexData.m_clVertexPosition.m_buffer ); } if( vertexBuffer->hasNormals() ) { int normalOffset = vertexBuffer->getNormalOffset(); int normalStride = vertexBuffer->getNormalStride(); ciErrNum = clSetKernelArg(outputKernel, 6, sizeof(int), &normalOffset ); ciErrNum = clSetKernelArg(outputKernel, 7, sizeof(int), &normalStride ); ciErrNum = clSetKernelArg(outputKernel, 8, sizeof(cl_mem), (void*)&vertexData.m_clVertexNormal.m_buffer ); } size_t numWorkItems = workGroupSize*((vertexData.getNumVertices() + (workGroupSize-1)) / workGroupSize); ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, outputKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); if( ciErrNum != CL_SUCCESS ) { btAssert( 0 && "enqueueNDRangeKernel(copySoftBodyToVertexBuffer)"); } ciErrNum = clEnqueueReleaseGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, 0); if( ciErrNum != CL_SUCCESS ) { btAssert( 0 && "clEnqueueReleaseGLObjects(copySoftBodyToVertexBuffer)"); } } else { btAssert( "Undefined output for this solver output" == false ); } // clFinish in here may not be the best thing. It's possible that we should have a waitForFrameComplete function. clFinish(m_cqCommandQue); } // btSoftBodySolverOutputCLtoGL::outputToVertexBuffers
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code // the vertex shader simply passes through data std::string vertex_source = "#version 430\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the geometry shader creates the billboard quads std::string geometry_source = "#version 430\n" "uniform mat4 View;\n" "uniform mat4 Projection;\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices = 4) out;\n" "out vec2 txcoord;\n" "void main() {\n" " vec4 pos = View*gl_in[0].gl_Position;\n" " txcoord = vec2(-1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2(-1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" "}\n"; // the fragment shader creates a bell like radial color distribution std::string fragment_source = "#version 330\n" "in vec2 txcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" " FragColor = s*vec4(0.3,0.3,1.0,1);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler geometry shader geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); source = geometry_source.c_str(); length = geometry_source.size(); glShaderSource(geometry_shader, 1, &source, &length); glCompileShader(geometry_shader); if(!check_shader_compile_status(geometry_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, geometry_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint View_location = glGetUniformLocation(shader_program, "View"); GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); std::string compute_source = "#version 430\n" "layout(local_size_x=256) in;\n" "uniform vec3 center[3];\n" "uniform float radius[3];\n" "uniform vec3 g;\n" "uniform float dt;\n" "uniform float bounce;\n" "uniform int seed;\n" "uniform layout(rgba32f) imageBuffer particles;\n" "float hash(int x) {\n" " x = x*1235167 + int(gl_GlobalInvocationID)*948737 + seed*9284365;\n" " x = (x >> 13) ^ x;\n" " return ((x * (x * x * 60493 + 19990303) + 1376312589) & 0x7fffffff)/float(0x7fffffff-1);\n" "}\n" "void main() {\n" " int index = int(gl_GlobalInvocationID);\n" " vec3 inposition = imageLoad(particles, 2*index).xyz;\n" " vec3 invelocity = imageLoad(particles, 2*index+1).xyz;\n" " vec3 outvelocity = invelocity;\n" " for(int j = 0;j<3;++j) {\n" " vec3 diff = inposition-center[j];\n" " float dist = length(diff);\n" " float vdot = dot(diff, invelocity);\n" " if(dist<radius[j] && vdot<0.0)\n" " outvelocity -= bounce*diff*vdot/(dist*dist);\n" " }\n" " outvelocity += dt*g;\n" " vec3 outposition = inposition + dt*outvelocity;\n" " if(outposition.y < -30.0)\n" " {\n" " outvelocity = vec3(0,0,0);\n" " outposition = 0.5-vec3(hash(3*index+0),hash(3*index+1),hash(3*index+2));\n" " outposition = vec3(0,20,0) + 5.0*outposition;\n" " }\n" " imageStore(particles, 2*index, vec4(outposition,1));\n" " imageStore(particles, 2*index+1, vec4(outvelocity,1));\n" "}\n"; // program and shader handles GLuint compute_program, compute_shader; // create and compiler vertex shader compute_shader = glCreateShader(GL_COMPUTE_SHADER); source = compute_source.c_str(); length = compute_source.size(); glShaderSource(compute_shader, 1, &source, &length); glCompileShader(compute_shader); if(!check_shader_compile_status(compute_shader)) { return 1; } // create program compute_program = glCreateProgram(); // attach shaders glAttachShader(compute_program, compute_shader); // link the program and check for errors glLinkProgram(compute_program); check_program_link_status(compute_program); GLint center_location = glGetUniformLocation(compute_program, "center"); GLint radius_location = glGetUniformLocation(compute_program, "radius"); GLint g_location = glGetUniformLocation(compute_program, "g"); GLint dt_location = glGetUniformLocation(compute_program, "dt"); GLint bounce_location = glGetUniformLocation(compute_program, "bounce"); GLint seed_location = glGetUniformLocation(compute_program, "seed"); GLint particles_location = glGetUniformLocation(compute_program, "particles"); const int particles = 128*1024; // randomly place particles in a cube std::vector<glm::vec4> vertexData(2*particles); for(int i = 0;i<particles;++i) { // initial position vertexData[2*i+0] = glm::vec4( 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX, 0 ); vertexData[2*i+0] = glm::vec4(0.0f,20.0f,0.0f,1) + 5.0f*vertexData[2*i+0]; // initial velocity vertexData[2*i+1] = glm::vec4(0,0,0,0); } // generate vbos and vaos GLuint vao, vbo; glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); // fill with initial data glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // set up generic attrib pointers glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0 + 4*sizeof(GLfloat)); // "unbind" vao glBindVertexArray(0); // texture handle GLuint buffer_texture; // generate and bind the buffer texture glGenTextures(1, &buffer_texture); glBindTexture(GL_TEXTURE_BUFFER, buffer_texture); // tell the buffer texture to use glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, vbo); // we are blending so no depth testing glDisable(GL_DEPTH_TEST); // enable blending glEnable(GL_BLEND); // and set the blend function to result = 1*source + 1*destination glBlendFunc(GL_ONE, GL_ONE); // define spheres for the particles to bounce off const int spheres = 3; glm::vec3 center[spheres]; float radius[spheres]; center[0] = glm::vec3(0,12,1); radius[0] = 3; center[1] = glm::vec3(-3,0,0); radius[1] = 7; center[2] = glm::vec3(5,-10,0); radius[2] = 12; // physical parameters float dt = 1.0f/60.0f; glm::vec3 g(0.0f, -9.81f, 0.0f); float bounce = 1.2f; // inelastic: 1.0f, elastic: 2.0f int current_buffer=0; running = true; while(running) { // get the time in seconds float t = glfwGetTime(); // terminate on excape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // use the transform shader program glUseProgram(compute_program); // set the uniforms glUniform3fv(center_location, 3, reinterpret_cast<GLfloat*>(center)); glUniform1fv(radius_location, 3, reinterpret_cast<GLfloat*>(radius)); glUniform3fv(g_location, 1, glm::value_ptr(g)); glUniform1f(dt_location, dt); glUniform1f(bounce_location, bounce); glUniform1i(seed_location, std::rand()); glBindImageTexture(0, buffer_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); glUniform1i(particles_location, 0); glDispatchCompute(particles/256, 1, 1); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)); // make the camera rotate around the origin View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); // set the uniform glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); // bind the current vao glBindVertexArray(vao); // draw glDrawArrays(GL_POINTS, 0, particles); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteTextures(1, &buffer_texture); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, geometry_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(geometry_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glDetachShader(compute_program, compute_shader); glDeleteShader(compute_shader); glDeleteProgram(compute_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // select opengl version glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code // the vertex shader simply passes through data std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the geometry shader creates the billboard quads std::string geometry_source = "#version 330\n" "uniform mat4 View;\n" "uniform mat4 Projection;\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices = 4) out;\n" "out vec2 txcoord;\n" "void main() {\n" " vec4 pos = View*gl_in[0].gl_Position;\n" " txcoord = vec2(-1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2(-1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" "}\n"; // the fragment shader creates a bell like radial color distribution std::string fragment_source = "#version 330\n" "in vec2 txcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" " FragColor = s*vec4(0.3,0.3,1.0,1);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler geometry shader geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); source = geometry_source.c_str(); length = geometry_source.size(); glShaderSource(geometry_shader, 1, &source, &length); glCompileShader(geometry_shader); if(!check_shader_compile_status(geometry_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, geometry_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint View_location = glGetUniformLocation(shader_program, "View"); GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); const int particles = 128*1024; // randomly place particles in a cube std::vector<glm::vec3> vertexData(particles); std::vector<glm::vec3> velocity(particles); for(int i = 0; i<particles; ++i) { vertexData[i] = glm::vec3(0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX); vertexData[i] = glm::vec3(0.0f,20.0f,0.0f) + 5.0f*vertexData[i]; } int buffercount = 3; // generate vbos and vaos GLuint vao[buffercount], vbo[buffercount]; glGenVertexArrays(buffercount, vao); glGenBuffers(buffercount, vbo); for(int i = 0; i<buffercount; ++i) { glBindVertexArray(vao[i]); glBindBuffer(GL_ARRAY_BUFFER, vbo[i]); // fill with initial data glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), &vertexData[0], GL_DYNAMIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); } // "unbind" vao glBindVertexArray(0); // we are blending so no depth testing glDisable(GL_DEPTH_TEST); // enable blending glEnable(GL_BLEND); // and set the blend function to result = 1*source + 1*destination glBlendFunc(GL_ONE, GL_ONE); // define spheres for the particles to bounce off const int spheres = 3; glm::vec3 center[spheres]; float radius[spheres]; center[0] = glm::vec3(0,12,1); radius[0] = 3; center[1] = glm::vec3(-3,0,0); radius[1] = 7; center[2] = glm::vec3(5,-10,0); radius[2] = 12; // physical parameters float dt = 1.0f/60.0f; glm::vec3 g(0.0f, -9.81f, 0.0f); float bounce = 1.2f; // inelastic: 1.0f, elastic: 2.0f int current_buffer=0; running = true; while(running) { // get the time in seconds float t = glfwGetTime(); // terminate on escape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // update physics for(int i = 0; i<particles; ++i) { // resolve sphere collisions for(int j = 0; j<spheres; ++j) { glm::vec3 diff = vertexData[i]-center[j]; float dist = glm::length(diff); if(dist<radius[j] && glm::dot(diff, velocity[i])<0.0f) velocity[i] -= bounce*diff/(dist*dist)*glm::dot(diff, velocity[i]); } // euler iteration velocity[i] += dt*g; vertexData[i] += dt*velocity[i]; // reset particles that fall out to a starting position if(vertexData[i].y<-30.0) { vertexData[i] = glm::vec3( 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX ); vertexData[i] = glm::vec3(0.0f,20.0f,0.0f) + 5.0f*vertexData[i]; velocity[i] = glm::vec3(0,0,0); } } // bind a buffer to upload to glBindBuffer(GL_ARRAY_BUFFER, vbo[(current_buffer+buffercount-1)%buffercount]); // explicitly invalidate the buffer glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), 0, GL_DYNAMIC_DRAW); // map the buffer glm::vec3 *mapped = reinterpret_cast<glm::vec3*>( glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3)*vertexData.size(), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ) ); // copy data into the mapped memory std::copy(vertexData.begin(), vertexData.end(), mapped); // unmap the buffer glUnmapBuffer(GL_ARRAY_BUFFER); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)); // make the camera rotate around the origin View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); // set the uniform glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); // bind the current vao glBindVertexArray(vao[current_buffer]); // draw glDrawArrays(GL_POINTS, 0, particles); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); // advance buffer index current_buffer = (current_buffer + 1) % buffercount; } // delete the created objects glDeleteVertexArrays(buffercount, vao); glDeleteBuffers(buffercount, vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, geometry_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(geometry_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; UserData userdata; userdata.running = true; GLWTConfig glwt_config; glwt_config.red_bits = 8; glwt_config.green_bits = 8; glwt_config.blue_bits = 8; glwt_config.alpha_bits = 8; glwt_config.depth_bits = 24; glwt_config.stencil_bits = 8; glwt_config.samples = 0; glwt_config.sample_buffers = 0; glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE; glwt_config.api_version_major = 3; glwt_config.api_version_minor = 3; GLWTAppCallbacks app_callbacks; app_callbacks.error_callback = error_callback; app_callbacks.userdata = &userdata; if(glwtInit(&glwt_config, &app_callbacks) != 0) { std::cerr << "failed to init GLWT" << std::endl; return 1; } GLWTWindowCallbacks win_callbacks; win_callbacks.close_callback = close_callback; win_callbacks.expose_callback = 0; win_callbacks.resize_callback = 0; win_callbacks.show_callback = 0; win_callbacks.focus_callback = 0; win_callbacks.key_callback = key_callback, win_callbacks.motion_callback = 0; win_callbacks.button_callback = 0; win_callbacks.mouseover_callback = 0; win_callbacks.userdata = &userdata; // create a window GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0); if(window == 0) { std::cerr << "failed to open window" << std::endl; glwtQuit(); return 1; } if (glxwInit()) { std::cerr << "failed to init GLXW" << std::endl; glwtWindowDestroy(window); glwtQuit(); return 1; } glwtWindowShow(window, 1); glwtMakeCurrent(window); glwtSwapInterval(window, 1); // shader source code // the vertex shader simply passes through data std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the geometry shader creates the billboard quads std::string geometry_source = "#version 330\n" "uniform mat4 View;\n" "uniform mat4 Projection;\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices = 4) out;\n" "out vec2 txcoord;\n" "void main() {\n" " vec4 pos = View*gl_in[0].gl_Position;\n" " txcoord = vec2(-1,-1);\n" " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1,-1);\n" " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2(-1, 1);\n" " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1, 1);\n" " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" " EmitVertex();\n" "}\n"; // the fragment shader creates a bell like radial color distribution std::string fragment_source = "#version 330\n" "in vec2 txcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" " FragColor = s*vec4(1,0.9,0.6,1);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler geometry shader geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); source = geometry_source.c_str(); length = geometry_source.size(); glShaderSource(geometry_shader, 1, &source, &length); glCompileShader(geometry_shader); if(!check_shader_compile_status(geometry_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, geometry_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint View_location = glGetUniformLocation(shader_program, "View"); GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); // vao and vbo handle GLuint vao, vbo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); const int particles = 128*1024; // create a galaxylike distribution of points std::vector<GLfloat> vertexData(particles*3); for(int i = 0;i<particles;++i) { int arm = 3*(std::rand()/float(RAND_MAX)); float alpha = 1/(0.1f+std::pow(std::rand()/float(RAND_MAX),0.7f))-1/1.1f; float r = 4.0f*alpha; alpha += arm*2.0f*3.1416f/3.0f; vertexData[3*i+0] = r*std::sin(alpha); vertexData[3*i+1] = 0; vertexData[3*i+2] = r*std::cos(alpha); vertexData[3*i+0] += (4.0f-0.2*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+ std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX))); vertexData[3*i+1] += (2.0f-0.1*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+ std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX))); vertexData[3*i+2] += (4.0f-0.2*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+ std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX))); } // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // "unbind" vao glBindVertexArray(0); // we are blending so no depth testing glDisable(GL_DEPTH_TEST); // enable blending glEnable(GL_BLEND); // and set the blend function to result = 1*source + 1*destination glBlendFunc(GL_ONE, GL_ONE); while(userdata.running) { // get the time in seconds float t = glwtGetNanoTime()*1.e-9f; // update events glwtEventHandle(0); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -50.0f)); // make the camera rotate around the origin View = glm::rotate(View, 30.0f*std::sin(0.1f*t), glm::vec3(1.0f, 0.0f, 0.0f)); View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); // set the uniform glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); // bind the vao glBindVertexArray(vao); // draw glDrawArrays(GL_POINTS, 0, particles); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { userdata.running = false; } // finally swap buffers glwtSwapBuffers(window); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, geometry_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(geometry_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glwtWindowDestroy(window); glwtQuit(); return 0; }
void Terrain::InitVB(ID3D11Device* device) { std::vector<Vertex::TerrainVertex> vertexData(mTerrainData.width * mTerrainData.height); UINT cellsWide = mTerrainData.width - 1; UINT cellsHigh = mTerrainData.height - 1; for (int row = 0; row < mTerrainData.height; ++row) { for (int col = 0; col < mTerrainData.width; ++col) { UINT index = row * mTerrainData.width + col; vertexData[index].pos = XMFLOAT3(col * mTerrainData.cellWidth, mHeightMap[index], row * mTerrainData.cellHeight); float u = mTerrainData.texTilesWide / mTerrainData.width; u *= col; float v = mTerrainData.texTilesHigh / mTerrainData.height; v *= row; vertexData[index].tiledTex.x = u; vertexData[index].tiledTex.y = v; u = (float)col / (mTerrainData.width - 1); v = (float)row / (mTerrainData.height - 1); vertexData[index].tex.x = u; vertexData[index].tex.y = v; } } std::vector<XMFLOAT3> normals; for (int row = 0; row < cellsHigh; ++row) { for (int col = 0; col < cellsWide; ++col) { //determine the row and column in terms of vertices given the //cell row and column UINT top = row + 1; UINT right = col + 1; UINT bot = row; UINT left = col; XMVECTOR A = XMVectorSet(0.0f, mHeightMap[top * mTerrainData.width + left] - mHeightMap[bot * mTerrainData.width + left], mTerrainData.cellHeight, 0.0f); XMVECTOR B = XMVectorSet(mTerrainData.cellWidth, mHeightMap[bot * mTerrainData.width + right] - mHeightMap[bot * mTerrainData.width + left], 0.0f, 0.0f); XMVECTOR C = XMVectorSet(mTerrainData.cellWidth, mHeightMap[top * mTerrainData.width + right] - mHeightMap[top * mTerrainData.width + left], 0.0f, 0.0f); XMVECTOR D = XMVectorSet(0.0f, mHeightMap[top * mTerrainData.width + right] - mHeightMap[bot * mTerrainData.width + right], mTerrainData.cellHeight, 0.0f); XMVECTOR topNormal = XMVector3Cross(D, C); XMVECTOR botNormal = XMVector3Cross(A, B); topNormal = XMVector3Normalize(topNormal); botNormal = XMVector3Normalize(botNormal); XMFLOAT3 topNormalF3, botNormalF3; XMStoreFloat3(&topNormalF3, topNormal); XMStoreFloat3(&botNormalF3, botNormal); normals.push_back(topNormalF3); normals.push_back(botNormalF3); } } for (int row = 0; row < mTerrainData.height; ++row) { for (int col = 0; col < mTerrainData.width; ++col) { UINT index = row * mTerrainData.width + col; int top = row; int bot = row - 1; int left = col - 1; int right = col; int normalCounter = 0; XMVECTOR normsCombined = XMVectorZero(); //get the two top left normals if (top < cellsHigh && left >= 0) { UINT topLeftIndex = (top * cellsWide + left) * 2; normsCombined = normsCombined + XMLoadFloat3(&normals[topLeftIndex]); normsCombined = normsCombined + XMLoadFloat3(&normals[topLeftIndex + 1]); normalCounter += 2; } //get the bottom left normal if (bot >= 0 && left >= 0) { UINT botLeftIndex = (bot * cellsWide + left) * 2; normsCombined = normsCombined + XMLoadFloat3(&normals[botLeftIndex]); normalCounter++; } //get the top right normal if (top < cellsHigh && right < cellsWide) { UINT topRightIndex = (top * cellsWide + right) * 2; normsCombined = normsCombined + XMLoadFloat3(&normals[topRightIndex]); normalCounter++; } //get the two bot right normals if (bot >= 0 && right < cellsWide) { UINT botRightIndex = (bot * cellsWide + right) * 2; normsCombined = normsCombined + XMLoadFloat3(&normals[botRightIndex]); normsCombined = normsCombined + XMLoadFloat3(&normals[botRightIndex + 1]); normalCounter += 2; } normsCombined = normsCombined / (float)normalCounter; XMStoreFloat3(&(vertexData[index].normal), normsCombined); } } D3D11_BUFFER_DESC vbd; vbd.Usage = D3D11_USAGE_IMMUTABLE; vbd.ByteWidth = sizeof(Vertex::TerrainVertex) * vertexData.size(); vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbd.CPUAccessFlags = 0; vbd.MiscFlags = 0; vbd.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA vinitData; vinitData.pSysMem = &vertexData[0]; HR(device->CreateBuffer(&vbd, &vinitData, &mVB)); }
v[3].set(itemCenter, verticalCenter, +1.0f, currentY); usedVertices += 4; } void BindlingLoopsGeometry::addCollapsedEvent(float horizontalCenterSource, float horizontalCenterTarget, float verticalCenterSource, float verticalCenterTarget) { // The source event should always be above the parent event because ranges are perfectly nested // and events are ordered by start time. QTC_ASSERT(verticalCenterSource > verticalCenterTarget, /**/); float tilt = horizontalCenterSource < horizontalCenterTarget ? +0.3f : -0.3f; Point2DWithOffset *v = vertexData() + usedVertices; v[0].set(horizontalCenterSource, verticalCenterSource, -0.3f, tilt); v[1].set(horizontalCenterSource, verticalCenterSource, -0.3f, tilt); v[2].set(horizontalCenterSource, verticalCenterSource, +0.3f, -tilt); v[3].set(horizontalCenterTarget, verticalCenterTarget, -0.3f, tilt); v[4].set(horizontalCenterTarget, verticalCenterTarget, +0.3f, -tilt); v[5].set(horizontalCenterTarget, verticalCenterTarget, -1.0f, -1.0f); v[6].set(horizontalCenterTarget, verticalCenterTarget, +1.0f, -1.0f); v[7].set(horizontalCenterTarget, verticalCenterTarget, -1.0f, +1.0f); v[8].set(horizontalCenterTarget, verticalCenterTarget, +1.0f, +1.0f); v[9].set(horizontalCenterTarget, verticalCenterTarget, -0.3f, tilt); v[10].set(horizontalCenterTarget, verticalCenterTarget, +0.3f, -tilt); v[11].set(horizontalCenterSource, verticalCenterSource, -0.3f, tilt); v[12].set(horizontalCenterSource, verticalCenterSource, +0.3f, -tilt);
void StaticMesh::Create(const char* fileName) { char baseDir[256]; char fileNameWoExt[256]; char tempPath[256]; _splitpath_s(fileName, nullptr, 0, baseDir, sizeof(baseDir), fileNameWoExt, sizeof(baseDir), nullptr, 0); // キャッシュファイル名 snprintf(tempPath, sizeof(tempPath), "%s%s.cache", baseDir, fileNameWoExt); std::ifstream cacheFile(tempPath, std::ios::in | std::ios::binary); if (cacheFile) { /** キャッシュから読み込み **/ // ファイル全体をリード cacheFile.seekg(0, std::fstream::end); uint32_t eofPos = (uint32_t)cacheFile.tellg(); cacheFile.clear(); cacheFile.seekg(0, std::fstream::beg); uint32_t begPos = (uint32_t)cacheFile.tellg(); uint32_t size = eofPos - begPos; std::unique_ptr<uint8_t> cacheData(new uint8_t[size]); cacheFile.read((char*)cacheData.get(), size); // パース const CacheHeader* header = (CacheHeader*)cacheData.get(); const Shape* shapes = (Shape*)(cacheData.get() + header->offsetToShapes); shapes_.resize(header->shapeNum); memcpy(&shapes_[0], shapes, sizeof(Shape) * header->shapeNum); uint32_t vtxStride = ComputeVertexStride(header->vertexAttrs); vertexBuffer_.Create(cacheData.get() + header->offsetToVertices, vtxStride * header->vertexNum, header->vertexAttrs); indexBuffer_.Create(cacheData.get() + header->offsetToIndeces, sizeof(uint32_t) * header->vertexNum, INDEX_BUFFER_STRIDE_U32); const char* materials = (const char*)(cacheData.get() + header->offsetToMaterial); materials_.resize(header->materialNum); std::unordered_map<std::string, uint32_t> textureMap; for (size_t i = 0; i < (uint32_t)materials_.size(); i++) { const char* m = materials + (256 * i); ZeroMemory(&materials_[i], sizeof(materials_[i])); // テクスチャ検索 if (strlen(m) > 0) { Texture* texture = nullptr; auto iter = textureMap.find(m); if (iter != textureMap.end()) { texture = textures_[iter->second]; } else { texture = new Texture(); snprintf(tempPath, sizeof(tempPath), "%s%s", baseDir, m); texture->LoadFromFile(tempPath); textures_.push_back(texture); uint32_t index = (uint32_t)textures_.size() - 1; textureMap[m] = index; } materials_[i].albedo = texture; } } } else { /** キャッシュがなかったらobjを読み込み **/ tinyobj::attrib_t attrib; std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::material_t> materials; Printf("Loading %s\n", fileName); std::string err; if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, fileName, baseDir, true)) { if (!err.empty()) { Printf(err.c_str()); } Printf("Failed to load/parse .obj.\n"); return; } //Printf("# of vertices : %d\n", (attrib.vertices.size() / 3)); //Printf("# of normals : %d\n", (attrib.normals.size() / 3)); //Printf("# of texcoords : %d\n", (attrib.texcoords.size() / 2)); //Printf("# of shapes : %d\n", shapes.size()); //Printf("# of materials : %d\n", materials.size()); // 現状はすべてのシェイプで頂点構造が一致している前提で処理しているため1つの頂点バッファにすべて入っている // TODO:tangent, bitangent計算 uint32_t vtxAttrs = VERTEX_ATTR_FLAG_POSITION; vtxAttrs |= (attrib.normals.size() > 0) ? VERTEX_ATTR_FLAG_NORMAL : 0; vtxAttrs |= (attrib.texcoords.size() > 0) ? VERTEX_ATTR_FLAG_TEXCOORD0 : 0; uint32_t vtxStride = ComputeVertexStride(vtxAttrs); // 全インデックス数を計算 uint32_t totalIndexNum = 0; for (auto& shape : shapes) { totalIndexNum += static_cast<uint32_t>(shape.mesh.indices.size()); } // 頂点をインデックス展開するためトータルインデックス数分の頂点バッファを確保 std::unique_ptr<uint8_t> vertexData(new uint8_t[vtxStride * totalIndexNum]); std::unique_ptr<uint8_t> indexData(new uint8_t[sizeof(uint32_t) * totalIndexNum]); uint32_t currentIndex = 0; uint32_t* currentIndexBufferPtr = reinterpret_cast<uint32_t*>(indexData.get()); for (uint32_t i = 0; i < shapes.size(); i++) { auto& shape = shapes[i]; Assert(shape.mesh.num_face_vertices.size() == shape.mesh.material_ids.size()); // For each face uint32_t currentMaterial = 0xffffffff; Shape currentShape; for (size_t f = 0; f < shape.mesh.num_face_vertices.size(); f++) { Assert(shape.mesh.num_face_vertices[f] == 3); // 三角形化済みのはず // マテリアルの切り替わり判定 if (currentMaterial != shape.mesh.material_ids[f]) { if (currentMaterial != 0xffffffff) { currentShape.indexCount = currentIndex - currentShape.indexStart; shapes_.push_back(currentShape); } currentMaterial = shape.mesh.material_ids[f]; currentShape.materialIndex = currentMaterial; currentShape.indexStart = currentIndex; currentShape.indexCount = 0; } // For each vertex in the face uint32_t ptrOffset = 0; uint8_t* currentVertexBufferPtr = vertexData.get() + (vtxStride * currentIndex); for (size_t v = 0; v < 3; v++) { tinyobj::index_t idx = shape.mesh.indices[(f * 3) + v]; // position memcpy(currentVertexBufferPtr + ptrOffset, &attrib.vertices[idx.vertex_index * 3], 12); ptrOffset += 12; // normal if (vtxAttrs & VERTEX_ATTR_FLAG_NORMAL) { memcpy(currentVertexBufferPtr + ptrOffset, &attrib.normals[idx.normal_index * 3], 12); ptrOffset += 12; } // texcoord if (vtxAttrs & VERTEX_ATTR_FLAG_TEXCOORD0) { float2* uv = reinterpret_cast<float2*>(currentVertexBufferPtr + ptrOffset); uv->x = attrib.texcoords[idx.texcoord_index * 2 + 0]; uv->y = 1.0f - attrib.texcoords[idx.texcoord_index * 2 + 1]; // OpenGL -> DirectX ptrOffset += 8; } currentIndexBufferPtr[currentIndex] = currentIndex; currentIndex++; } } // 最後のマテリアル分追加 currentShape.indexCount = currentIndex - currentShape.indexStart; shapes_.push_back(currentShape); } vertexBuffer_.Create(vertexData.get(), vtxStride * totalIndexNum, vtxAttrs); indexBuffer_.Create(indexData.get(), sizeof(uint32_t) * totalIndexNum, INDEX_BUFFER_STRIDE_U32); // マテリアル materials_.resize(materials.size()); std::unordered_map<std::string, uint32_t> textureMap; for (size_t i = 0; i < (uint32_t)materials_.size(); i++) { auto& m = materials[i]; ZeroMemory(&materials_[i], sizeof(materials_[i])); // テクスチャ検索 if (m.diffuse_texname.size() > 0) { Texture* texture = nullptr; auto iter = textureMap.find(m.diffuse_texname); if (iter != textureMap.end()) { texture = textures_[iter->second]; } else { texture = new Texture(); snprintf(tempPath, sizeof(tempPath), "%s%s", baseDir, m.diffuse_texname.c_str()); texture->LoadFromFile(tempPath); textures_.push_back(texture); uint32_t index = (uint32_t)textures_.size() - 1; textureMap[m.diffuse_texname] = index; } materials_[i].albedo = texture; } } // 読み込み高速化のためのキャッシュデータを生成 { snprintf(tempPath, sizeof(tempPath), "%s%s.cache", baseDir, fileNameWoExt); std::ofstream file(tempPath, std::ios::out | std::ios::binary); CacheHeader header; header.shapeNum = (uint16_t)shapes_.size(); header.materialNum = (uint16_t)materials_.size(); header.vertexAttrs = (uint16_t)vtxAttrs; header.vertexNum = totalIndexNum; header.offsetToShapes = sizeof(CacheHeader); header.offsetToVertices = header.offsetToShapes + sizeof(Shape) * header.shapeNum; header.offsetToIndeces = header.offsetToVertices + (vtxStride * totalIndexNum); header.offsetToMaterial = header.offsetToIndeces + (sizeof(uint32_t) * totalIndexNum); file.write((char*)&header, sizeof(header)); // シェイプ for (auto& s : shapes_) { file.write((char*)&s, sizeof(s)); } // 頂点 file.write((char*)vertexData.get(), vtxStride * totalIndexNum); // インデックス file.write((char*)indexData.get(), sizeof(uint32_t) * totalIndexNum); // マテリアル for (auto& m : materials) { FillMemory(tempPath, sizeof(tempPath), 0); snprintf(tempPath, sizeof(tempPath), "%s", m.diffuse_texname.c_str()); file.write(tempPath, sizeof(tempPath)); } } } }