OpenGL C ++ के साथ बनावट का प्रतिपादन
मैं एक बनावट के लिए कुछ बहुभुज प्रस्तुत करने की कोशिश कर रहा हूं, और फिर स्क्रीन को बनावट प्रदान करता हूं। मुझे यकीन नहीं है कि मेरे कोड को कैसे डीबग करना है क्योंकि इसके लिए ओपन की आंतरिक स्थिति की जांच करने की आवश्यकता होगी, इसलिए मैं अपने द्वारा किए गए त्रुटि को इंगित करने से अधिक खुद को डीबग करने के सुझावों की सराहना करूंगा। वैसे भी, मैंने उस कोड की टिप्पणी की जिसे मैंने समझाते हुए लिखा था कि मैं प्रत्येक पंक्ति से क्या करने की उम्मीद करता हूं।
यहाँ एक विवरण दिया गया है कि कोड क्या करना चाहिए। मूल रूप से, मैंने एक शीर्ष छायादार बनाया, जो टुकड़े करने वाले को स्थिति, यूवी और रंग प्रदान करता है। टुकड़े टुकड़े करना बनावट के नमूने को सक्रिय करने के लिए एक समान है, अन्यथा यह सिर्फ इनपुट रंग का उत्पादन करेगा। दोनों मामलों में, रंग एक समान रंग से गुणा किया जाता है। पहले मैं एक बनावट बनाता हूं, और मैं इसे परीक्षण करने के लिए लाल और हरे रंग के कच्चे पिक्सेल डेटा के साथ भरता हूं। इस बनावट को स्क्रीन पर संक्षिप्त रूप से प्रस्तुत किया गया है (जैसा कि मैंने इसे आरंभीकृत किया है, मैं लाल और हरे हिस्से को सही ढंग से देखता हूं)। तब मैं बनावट पर वास्तविक प्रतिपादन करने की कोशिश करता हूं। मैं इसके बीच में एक छोटे से नीले वर्ग को प्रस्तुत करने की कोशिश करता हूं (टुकड़े टुकड़े करने के लिए सैंपलर को निष्क्रिय कर दिया गया है, नीले रंग के लिए समान वर्दी) लेकिन मुझे इस नीले वर्ग को प्रदान की गई बनावट पर दिखाई नहीं दे सकता है।
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "utils.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
using namespace std;
#define numVAOs 1
#define numVBOs 1
GLuint shaderProgram;
GLuint unifUseTexture, unifInTexture, unifTMat, unifDrawColor;
GLuint texture;
GLuint textureFrameBuffer;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];
void drawRectangle() {
}
void init() {
// Compile the shaderProgram
shaderProgram = createShaderProgram("vertex.glsl","fragment.glsl");
// Retrieve the uniform location
unifUseTexture = glGetUniformLocation(shaderProgram,"useTexture");
unifInTexture = glGetUniformLocation(shaderProgram,"inTexture");
unifTMat = glGetUniformLocation(shaderProgram,"tMat");
unifDrawColor = glGetUniformLocation(shaderProgram,"drawColor");
// Create vertex array object and vertex buffer object
glGenVertexArrays(numVAOs,vao);
glBindVertexArray(vao[0]);
float xyzuvrgbaSquare[54] = {
/* C */ 1.0,-1.0,0.0, 1.0,0.0, 1.0,1.0,1.0,1.0,
/* A */ -1.0,1.0,0.0, 0.0,1.0, 1.0,1.0,1.0,1.0,
/* B */ 1.0,1.0,0.0, 1.0,1.0, 1.0,1.0,1.0,1.0,
/* A */ -1.0,1.0,0.0, 0.0,1.0, 1.0,1.0,1.0,1.0,
/* C */ 1.0,-1.0,0.0, 1.0,0.0, 1.0,1.0,1.0,1.0,
/* D */-1.0,-1.0,0.0, 0.0,0.0, 1.0,1.0,1.0,1.0
};
glGenBuffers(numVBOs,vbo);
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);
glBufferData(GL_ARRAY_BUFFER, 4*54,xyzuvrgbaSquare,GL_STATIC_DRAW);
// Associate vbo with the correct vertex attribute to display the rectangle
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,36,0); // inPosition
glVertexAttribPointer(1,4,GL_FLOAT,GL_FALSE,36,(void*)20); // inColor
glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,36,(void*)12); // inUV
glEnableVertexAttribArray(0); // location=0 in the shader
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
// Generate a small 128x128 texture. I followed the tutorial
// over http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/
// generate a frameBuffer to contain the texture
glGenFramebuffers(1,&textureFrameBuffer);
// Bind it, so when I will generate the texture it will be associated with it
glBindFramebuffer(GL_FRAMEBUFFER, textureFrameBuffer);
glGenTextures(1,&texture);
glBindTexture(GL_TEXTURE_2D,texture);
// Put some raw data inside of it for testing purposes. I will fill it
// half with green, half with red
unsigned char* imageRaw = new unsigned char[4*128*128];
for(int i=0; i<4*128*64; i+=4) {
imageRaw[i] = 255;
imageRaw[i+1] = 0;
imageRaw[i+2] = 0;
imageRaw[i+3] = 255;
imageRaw[4*128*64+i] = 0;
imageRaw[4*128*64+i+1] = 255;
imageRaw[4*128*64+i+2] = 0;
imageRaw[4*128*64+i+3] = 255;
}
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,imageRaw);
// Setup some required parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Draw a small blue square on the texture
// So, activate the previously compiled shader program and setup the uniforms
glUseProgram(shaderProgram);
// First, create a transform matrix to make the square smaller (20% of texture)
glm::mat4 tMat = glm::scale(glm::mat4(1.0f),glm::vec3(0.2,0.2,0));
glUniformMatrix4fv(unifTMat,1,GL_FALSE,glm::value_ptr(tMat));
// do not use a texture (ignore sampler2D in fragment shader)
glUniform1i(unifUseTexture,0);
// use the color BLUE for the rectangle
glUniform4f(unifDrawColor,0.0,0.0,1.0,1.0);
// Bind the textureFrameBuffer to render on the texture instead of the screen
glBindFramebuffer(GL_FRAMEBUFFER,textureFrameBuffer);
glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,texture,0);
GLenum drawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, drawBuffers);
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if( status != GL_FRAMEBUFFER_COMPLETE ) {
cout << "framebuffer status: " << status << endl;
}
// the vertex framebuffer and vertex attribute pointer have already been
// described, so I'll just do the draw call here
glDrawArrays(GL_TRIANGLES,0,6);
// Display the textore on screen
// Bind the screen framebuffer (0) so the following rendering will occurr on screen
glBindFramebuffer(GL_FRAMEBUFFER,0);
// Put a white background color
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
// Change properly the shader uniforms
glUniform4f(unifDrawColor,1.0,1.0,1.0,1.0); // multiply by white, no changes
glUniform1i(unifUseTexture,1); // set useTexture to True
// Create a transform matrix to scale the rectangle so that it uses up only half screen
tMat = glm::scale(glm::mat4(1.0f),glm::vec3(.5,.5,.0));
glUniformMatrix4fv(unifTMat,1,GL_FALSE,glm::value_ptr(tMat));
// Put the sampler2D
glActiveTexture(GL_TEXTURE0); // Work on texture0
// 0 because of (binding = 0) on the fragment shader
glBindTexture(GL_TEXTURE_2D,texture);
glDrawArrays(GL_TRIANGLES,0,6); // 6 vertices
}
int main(int argc, char** argv) {
// Build the window
if (!glfwInit()) exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
GLFWwindow* window = glfwCreateWindow(600,600,"Dashboard",NULL,NULL);
glfwMakeContextCurrent(window);
if(glewInit() != GLEW_OK) exit(EXIT_FAILURE);
glfwSwapInterval(1);
init();
while(!glfwWindowShouldClose(window)) {
//display(window,glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
संपादित करें: मैं shader कोड यहाँ रखना भूल गया, हालाँकि समस्या shader के भीतर नहीं है क्योंकि यह तब काम करता है जब इसका उपयोग स्क्रीन को बनावट प्रदान करने के लिए किया जाता है।
vertex.glsl:
#version 430
layout (location=0) in vec3 inPosition;
layout (location=1) in vec4 inColor;
layout (location=2) in vec2 inUV;
uniform mat4 tMat;
uniform vec4 drawColor;
out vec4 varyingColor;
out vec2 varyingUV;
void main(void) {
gl_Position = tMat * vec4(inPosition,1.0);
varyingColor = inColor*drawColor;
varyingUV = inUV;
}
टुकड़ा:।
#version 430
in vec4 varyingColor;
in vec2 varyingUV;
layout(location = 0) out vec4 color;
layout (binding=0) uniform sampler2D inTexture;
uniform bool useTexture;
void main(void) {
if( useTexture )
color = vec4(texture(inTexture,varyingUV).rgb,1.0) * varyingColor;
else
color = varyingColor;
}
जवाब
फ़्रेमबफ़र से जुड़ी बनावट, खिड़की की तुलना में एक अलग आकार है। इसलिए आप glViewportज्यामिति को चित्रित करने से पहले व्यूपोर्ट आयत ( ) को वर्तमान में बाध्य फ्रेमबफ़र के आकार के अनुसार समायोजित कर सकते हैं:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageRaw);
// [...]
glBindFramebuffer(GL_FRAMEBUFFER, textureFrameBuffer);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture,0);
glViewport(0, 0, 128, 128);
// [...]
glDrawArrays(GL_TRIANGLES, 0, 6);
// [...]
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, WIDTH, HEIGHT);
// [...]
glDrawArrays(GL_TRIANGLES, 0, 6);