ওপেনজিএল / জিএলএসএল: কিউব মানচিত্রটি রেন্ডার করব?


13

আমি কীভাবে আমার দৃশ্যের কিউব মানচিত্রে রেন্ডার করব তা বোঝার চেষ্টা করছি। আমি এটির জন্য কিছুটা আটকে গিয়েছি এবং বুঝতে পেরেছি আমি আপনাকে কিছু সাহায্য চাইব। আমি ওপেনজিএলে নতুন এবং আমি প্রথমবারের মতো এফবিও ব্যবহার করছি।

আমার কাছে বর্তমানে কিউব্যাম্যাপ বিএমপি ফাইল ব্যবহারের একটি কার্যকারী উদাহরণ রয়েছে এবং টুকরা শ্যাডারে স্যাম্পলারকিউব নমুনা প্রকারটি জিএল_আর। আমি শেডার কোডটি মোটেও পরিবর্তন করছি না। আমি কেবল এই সত্যটি পরিবর্তন করছি যে কিউব্যাপ বিএমপি ফাইলটি লোড করা এবং একটি কিউব্যাপে রেন্ডার করার জন্য নীচের কোডটি ব্যবহার করার চেষ্টা করছিলাম সেই ফাংশনটিতে আমি ফোন করব না।

আপনি নীচে দেখতে পাচ্ছেন যে আমি আবার টেক্সচারটিও জিএল_আর_সই 1 তে সংযুক্ত করছি। আমি ইউনিফর্ম সেট করার সময় এটি এমন হয়:

glUniform1i(getUniLoc(myProg, "Cubemap"), 1);

এটি এর মাধ্যমে আমার খণ্ডের শেডারে এটি অ্যাক্সেস করতে পারে uniform samplerCube Cubemap

আমি নীচের ফাংশনটি এভাবে কল করছি:

cubeMapTexture = renderToCubeMap(150, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);

এখন, আমি নীচের অঙ্কিত লুপটিতে বুঝতে পারি যে আমি + x, -x, + y, -y, + z, -z অক্ষটি দেখার জন্য দর্শন দিকটি পরিবর্তন করছি না। আমি বাস্তবায়নের আগে প্রথমে কিছু কাজ করতে দেখছিলাম। আমি অনুভব করেছি কোডটি এখন যেভাবে করা হচ্ছে তাতে আমার কমপক্ষে আমার কিছু লক্ষ্য করা উচিত।

আমি কিছুই দেখছি না, কেবল সোজা কালো। আমি আমার ব্যাকগ্রাউন্ডকে সাদা করে দিয়েছি এখনও অবজেক্টটি কালো। আমি কেবল কিউব্যাপের জমিন এবং এখনও কালো রঙের নমুনার জন্য আলোকপাত এবং রঙিনটি সরিয়েছি।

আমি ভাবছি যে আমার টেক্সচারটি জিএল_আরজিবি 8, জিএল_আরজিবিএ স্থাপন করার সময় সমস্যাটি ফর্ম্যাট ধরণের হতে পারে তবে আমি চেষ্টা করেছি:

GL_RGBA, GL_RGBA GL_RGB, GL_RGB

আমি ভেবেছিলাম এটি স্ট্যান্ডার্ড হবে যেহেতু আমরা ফ্রেমবফারের সাথে সংযুক্ত একটি টেক্সচারকে রেন্ডার করছি তবে আমি বিভিন্ন উদাহরণ দেখেছি যা বিভিন্ন এনাম মান ব্যবহার করে।

আমি প্রতিটি অঙ্কিত কলটিতে কিউব মানচিত্রের টেক্সচারকে আবদ্ধ করার চেষ্টা করেছি যা আমি কিউব মানচিত্রটি ব্যবহার করতে চাই:

glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapTexture);

এছাড়াও, আমি এফবিওর জন্য গভীরতার বাফার তৈরি করছি না যা আমি বেশিরভাগ উদাহরণে দেখেছি, কারণ আমি কেবল আমার ঘনক্ষেত্রের মানচিত্রের জন্য রঙিন বাফারটি চাইছি। সমস্যাটি কিনা তা দেখতে আমি আসলে একজনকে যুক্ত করেছি এবং এখনও একই ফলাফল পেয়েছি। আমি চেষ্টা করার সময় আমি এটির সাথে প্রতারণা করতে পারি।

আমাকে সঠিক দিক নির্দেশ করতে পারে এমন যে কোনও সহায়তা প্রশংসিত হবে।

GLuint renderToCubeMap(int size, GLenum InternalFormat, GLenum Format, GLenum Type)
    {

    // color cube map
    GLuint textureObject;
    int face;
    GLenum status;

    //glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE1);
    glGenTextures(1, &textureObject);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureObject);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    for (face = 0; face < 6; face++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, InternalFormat, size, size, 0, Format, Type, NULL);
    }

    // framebuffer object
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, textureObject, 0);

    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    printf("%d\"\n", status);
        printf("%d\n", GL_FRAMEBUFFER_COMPLETE);

    glViewport(0,0,size, size);

    for (face = 1; face < 6; face++) {

        drawSpheres();
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, textureObject, 0);

    }

     //Bind 0, which means render to back buffer, as a result, fb is unbound
       glBindFramebuffer(GL_FRAMEBUFFER, 0);

       return textureObject;
    }

আপনি কি পরীক্ষা করেছেন যে আপনার drawSpheresফাংশনটি আসলে কিছু দৃশ্যমান হয়? ফাংশন আসলে কিছু আঁকেন? আপনি যদি drawSpheresকেবল ফ্রেমবফারটি সাফ করতে পরিবর্তন করেন তবে কি হবে ?
নিকল বোলাস

হ্যাঁ. আমি দুটি পাস করছি। উপরের কোডের মধ্যে একটি, আসলে উপরে 6 টি কল। তারপরে আমি ফ্রেমবফার 0 তে রেন্ডার করার সময় ড্রস্পিয়ারগুলি কল করছি এবং এটি প্রদর্শিত হবে না।
জো জো সবুজ

এছাড়াও, আমি আমার ব্যাকগ্রাউন্ডটি সাদা করে দিয়েছি। সাদা রঙ কমপক্ষে জমিনে প্রদর্শিত হবে না?
জো সবুজ

আপনার কোডটি কি কোনও সাধারণ এফবিওর জন্য ভাল কাজ করে? আমি এটি যেভাবে বুঝতে পারি, একটি ঘনক্ষেত্রের মানচিত্রটি কেবল ছয়টি টেক্সচারের হওয়া উচিত এবং আপনার প্রতিটি আলাদা আলাদাভাবে রেন্ডার করতে হবে ..
জারি কম্প্পা

উত্তর:


10

ভাল, আমি গ্যারান্টি দিতে পারি না যে এটি আপনাকে কী ঘটছে তা নির্ধারণ করতে সহায়তা করবে। কোনও বিশেষ ত্রুটি সনাক্ত করতে আপনি কী করছেন সে সম্পর্কে আপনি কেবল পর্যাপ্ত তথ্য পোস্ট করেননি। যদিও আমি আপনার এক জিনিস সত্যিই দ্রুত সংশোধন করতে পারি:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, textureObject, 0);

...

for (face = 1; face < 6; face++) {
    drawSpheres();
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, textureObject, 0);
}

এটি কেবল drawSpheres পাঁচ বার কল করবে । আমি অনুমান করছি আপনি এটি 6 বার কল করতে চেয়েছিলেন।

তবে আমি একটি কার্যকরী উত্তর পোস্ট করতে পারি নোট করুন যে এই কোডটি আমার টিউটোরিয়াল সিরিজের পাশাপাশি চালানোর জন্য ডিজাইন করা হয়েছে , সুতরাং এটি কোডটির সাথে উল্লেখ করে যা উপস্থিত নেই। তবে এটি মূলত মেস তৈরির মতো জিনিস এবং আরও অনেক কিছু; সত্যিই গুরুত্বপূর্ণ কিছুই।

এখানে মূল বিষয়গুলি রয়েছে। মূল গোলকের অবজেক্টের জন্য শেডারগুলি।

ভার্টেক্স শ্যাডার:

#version 330

layout(std140) uniform;

layout(location = 0) in vec4 position;
layout(location = 2) in vec3 normal;

out vec3 modelSpaceNormal;

uniform Projection
{
    mat4 cameraToClipMatrix;
};

uniform mat4 modelToCameraMatrix;

void main()
{
    gl_Position = cameraToClipMatrix * (modelToCameraMatrix * position);
    modelSpaceNormal = normal;
}

খণ্ড শ্যাডার:

#version 330

in vec3 modelSpaceNormal;

uniform samplerCube cubeTexture;

out vec4 outputColor;

void main()
{
    outputColor = texture(cubeTexture, modelSpaceNormal);
//  outputColor = vec4(normalize(modelSpaceNormal), 1.0);
}

কিউম্যাপ টেক্সচারের তৈরি যা রেন্ডার টার্গেট হিসাবে ব্যবহৃত হবে:

void CreateCubeTexture()
{
    glGenTextures(1, &g_cubeTexture);
    glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    std::vector<GLubyte> testData(CUBE_TEXTURE_SIZE * CUBE_TEXTURE_SIZE * 256, 128);
    std::vector<GLubyte> xData(CUBE_TEXTURE_SIZE * CUBE_TEXTURE_SIZE * 256, 255);

    for(int loop = 0; loop < 6; ++loop)
    {
        if(loop)
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + loop, 0, GL_RGBA8,
                CUBE_TEXTURE_SIZE, CUBE_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &testData[0]);
        }
        else
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + loop, 0, GL_RGBA8,
                CUBE_TEXTURE_SIZE, CUBE_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &xData[0]);
        }
    }

    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}

আমি ডিবাগিং এইড হিসাবে প্রকৃতপক্ষে ডেটা দিয়ে টেক্সচারটি পূরণ করি (গ্লিটেক্স আইমেজ 2 ডি তে NUL পাস করার চেয়ে)। এটি নিশ্চিত করে যে টেক্সচারটি রেন্ডার টার্গেট হিসাবে ব্যবহার করা শুরু করার আগে সবকিছু কাজ করেছিল।

এছাড়াও, লক্ষ্য করুন যে আমি একটি BASE_LEVEL এবং MAX_LEVEL সরবরাহ করি। আমি সবসময় সৃষ্টির সাথে সাথেই আমার টেক্সচার দিয়ে এটি করি। এটি কেবল একটি ভাল অভ্যাস, কারণ টেক্সচারের সম্পূর্ণতা এবং মাইপম্যাপ পিরামিড সম্পর্কে কখনও কখনও ওপেনজিএল পিক হতে পারে। নিয়মগুলি মনে রাখার পরিবর্তে, আমি তাদের ধর্মীয়ভাবে সঠিক মানগুলিতে সেট করেছি।

এখানে মূল অঙ্কন ফাংশন:

void display()
{
    //Draw the cubemap.
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, g_framebuffer);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, g_depthbuffer);

    for(int loop = 0; loop < 6; ++loop)
        DrawFace(loop);

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

    //Draw the main scene.
    //The projection matrix is in a uniform buffer.
    ProjectionBlock projData;
    projData.cameraToClipMatrix = glm::perspective(90.0f,
        (g_viewportSize.x / (float)g_viewportSize.y), g_fzNear, g_fzFar);

    glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    glViewport(0, 0, (GLsizei)g_viewportSize.x, (GLsizei)g_viewportSize.y);

    glClearColor(0.75f, 0.75f, 1.0f, 1.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glutil::MatrixStack modelMatrix;
    modelMatrix.ApplyMatrix(g_viewPole.CalcMatrix());

    if(g_pSphere)
    {
        glutil::PushStack push(modelMatrix);

        glUseProgram(g_progMain.theProgram);
        glUniformMatrix4fv(g_progMain.modelToCameraMatrixUnif, 1, GL_FALSE,
            glm::value_ptr(modelMatrix.Top()));

        glActiveTexture(GL_TEXTURE0 + g_cubeTexUnit);
        glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

        g_pSphere->Render("lit");

        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

        glUseProgram(0);
    }

    glutPostRedisplay();
    glutSwapBuffers();
}

এটি রেফারেন্স দেয় DrawFace, যা কিউব্যাপের প্রদত্ত চেহারা আঁকবে। এটি নিম্নলিখিত হিসাবে প্রয়োগ করা হয়েছে:

void DrawFace(int iFace)
{
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
        GL_TEXTURE_CUBE_MAP_POSITIVE_X + iFace, g_cubeTexture, 0);

    GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
    if(status != GL_FRAMEBUFFER_COMPLETE)
        printf("Status error: %08x\n", status);

    //The projection matrix is in a uniform buffer.
    ProjectionBlock projData;
    projData.cameraToClipMatrix = glm::perspective(90.0f, 1.0f, g_fzNear, g_fzFar);

    glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    glViewport(0, 0, (GLsizei)CUBE_TEXTURE_SIZE, (GLsizei)CUBE_TEXTURE_SIZE);

    const glm::vec4 &faceColor = g_faceColors[iFace];
    glClearColor(faceColor.x, faceColor.y, faceColor.z, faceColor.w);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if(g_pSphere)
    {
        glutil::MatrixStack modelMatrix;
        modelMatrix.Translate(g_faceSphereLocs[iFace]);

        glUseProgram(g_progUnlit.theProgram);
        glUniformMatrix4fv(g_progUnlit.modelToCameraMatrixUnif, 1, GL_FALSE,
            glm::value_ptr(modelMatrix.Top()));

        const glm::vec4 &sphereColor = g_faceSphereColors[iFace];
        glUniform4fv(g_progUnlit.objectColorUnif, 1, glm::value_ptr(sphereColor));

        glActiveTexture(GL_TEXTURE0 + g_cubeTexUnit);
        glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

        g_pSphere->Render("flat");

        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
        glUseProgram(0);
    }
}

এই ফাংশনটি গ্লোবাল টেবিলগুলির একটি সেটকে উল্লেখ করে যা আমি প্রতিটি মুখকে একটি স্বতন্ত্র পটভূমির রঙ দিতে, একটি স্বতন্ত্র গোলকের রঙ দিতে এবং সেই মুখের জন্য গোলকটি (ক্যামেরা-স্পেসে) সঠিকভাবে স্থাপন করতে ব্যবহার করি।

এর জন্য DrawFaceমূল বিষয়গুলি হ'ল ।

একটি সাধারণ নিয়ম হিসাবে, যদি না আমার নির্দিষ্ট জ্ঞান না থাকে যে রাষ্ট্রটি সেট করা আছে, আমি সেই রাজ্যটি সেট করি। আমি যখনই কল করি তখন আমি ভিউপোর্টটি সেট করি DrawFace। আমি প্রতিবার প্রোজেকশন ম্যাট্রিক্স সেট করেছি। এগুলি অতিরিক্ত অতিরিক্ত; আমি বর্তমান এফবিও এবং গভীরতা রেন্ডারব্ফারের সাথে ঠিক যেমন করে displayকল করি সেই লুপের আগে সেগুলি আবার সেট করতে DrawFaceপারতাম।

কিন্তু আমি আরো বাফার, যা প্রতিটি মুখের জন্য আলাদা (যেহেতু প্রতিটি মুখ একটি ভিন্ন রঙ আছে) সাফ করুন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.