ওপেনগিএলে কীভাবে glOrtho () ব্যবহার করবেন?


88

আমি এর ব্যবহার বুঝতে পারি না glOrtho। এটির জন্য কী ব্যবহৃত হয় তা কেউ ব্যাখ্যা করতে পারেন?

এটি কি xy এবং z স্থানাঙ্কের সীমা নির্ধারণের জন্য ব্যবহৃত হয়?

glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);

এর অর্থ x, y এবং z রেঞ্জ -1 থেকে 1?


4
এই ভিডিওটি আমাকে অনেক সাহায্য করেছে।
ভিনিসিয়াস অররুদা

উত্তর:


155

এই ছবিটি একবার দেখুন: গ্রাফিকাল প্রজেকশনস এখানে চিত্র বর্ণনা লিখুন

glOrthoকমান্ড একটি "অবলিক" অভিক্ষেপ আপনি নিচের সারি মধ্যে দেখতে উৎপন্ন হয়। Z দিকের দিক থেকে ভার্টেক্সগুলি যত দূরেই থাকুক না কেন, তারা দূরত্বে চলে যাবে না।

আমি যখনই ওপেনগিএলে 2 ডি গ্রাফিকগুলি করার প্রয়োজন হয় ততবার আমি গ্লোঅর্থো ব্যবহার করি (যেমন স্বাস্থ্য বার, মেনু ইত্যাদি) প্রতিবার উইন্ডোটি পুনরায় আকার দেওয়ার পরে নিম্নলিখিত কোডটি ব্যবহার করে:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, windowWidth, windowHeight, 0.0f, 0.0f, 1.0f);

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

নোট করুন যে জেড মানগুলি 0 থেকে 1 পর্যন্ত ক্লিপ করা আছে So সুতরাং আপনি যখন আপনার ভার্টেক্সের অবস্থানের জন্য একটি জেড মান নির্দিষ্ট করবেন তখন সাবধান হন, এটি যদি এই সীমাটির বাইরে চলে যায় তবে এটি ক্লিপ হবে। অন্যথায় এটি যদি এই সীমার মধ্যে থাকে তবে জেড টেস্টগুলি বাদ দিয়ে পজিশনে এটির কোনও প্রভাব পড়বে না।


91
ওহে আমার godশ্বর আমি তোমাকে ভালবাসি অনলাইনে কোডটির এই একক লাইনটি খুঁজে পেতে / খুঁজে পেতে আপনার কতক্ষণ ধারণা আছে? আপনাকে ধন্যবাদ, আমি এর জন্য আপনার পরে আমার প্রথম জন্ম নেওয়া সন্তানের নাম রাখব
করপ্যাথি

4
দ্রষ্টব্য: (অ্যান্ড্রয়েডে) এমনকি যদি মডেলটির কেবল নেতিবাচক z মান থাকে তবে চূড়ান্ত (দূরবর্তী) প্যারামিটারের জন্য ইতিবাচক মান থাকা প্রয়োজন বলে মনে হয়। আমি একটি সাধারণ ত্রিভুজ পরীক্ষা করেছি (কুলিং অক্ষম সহ), এর উপরের দ্বার দিয়ে z= -2। যদি আমি ব্যবহার ত্রিভুজ অদৃশ্য ছিল glOrtho(.., 0.0f, -4.0f);, ..-1.0f, -3.0f)অথবা ..-3.0f, -1.0f)। দৃশ্যমান হওয়ার জন্য, দূরবর্তী প্যারামিটারটি পজিটিভ 2 বা ততোধিক হতে হবে; নিকটতম প্যারামিটারটি কী তা তা মনে হচ্ছে না। এর মধ্যে যে কোনো কাজ: ..0.0f, 2.0f), ..-1.0f, 2.0f), ..-3.0f, 2.0f), অথবা ..0.0f, 1000.0f
টুলমেকারস্টেভ

10
এটি ওপেনগ্লায় খারাপ টিউটোরিয়ালের পরিমাণ হাস্যকর।
বেসিকরেল

4
@ কারি, আশা করি এই লিঙ্কটি সাহায্য করতে পারে। > learnopengl.com/#!In-
অনুশীলন /

4
@ এমগুইন জেড রেঞ্জটি উল্লেখ করে যে আপনার জেড-নিকটবর্তী বিমান এবং আপনার জেড-দুর বিমানটি কোথায়। আপনি যখন আপনার জ্যামিতি আঁকবেন তখন দুটি জেড প্লেনের মধ্যে অবশ্যই এর Z মানগুলি হওয়া উচিত । যদি সেগুলি জেড প্লেনগুলির বাইরে পড়ে তবে আপনার জ্যামিতিটি রেন্ডার হবে না। এছাড়াও আপনার রেন্ডারারের গভীরতার জন্য কেবল একটি নির্দিষ্ট রেজোলিউশন রয়েছে। যদি আপনার দূরের বিমানটি 1000 ইউনিট দূরে স্থাপন করে থাকে এবং আপনি একে অপরের থেকে 0.1 ইউনিট দূরে সামান্য মুখের সাথে একটি ছোট্ট মডেল আঁকতে চেষ্টা করেন তবে ওপেনজিএল আপনাকে প্রয়োজনীয় গভীরতার সমাধান দিতে সক্ষম হবে না এবং আপনি জেড-ফাইটিং (ঝলকানি) পাবেন মুখের মধ্যে।
মাইকপোট

55

ন্যূনতম চলমান উদাহরণ

glOrtho: 2 ডি গেমস, অবজেক্টগুলি নিকটে এবং দূরে একই আকারে উপস্থিত হয়:

এখানে চিত্র বর্ণনা লিখুন

glFrustrum: 3 ডি এর মতো আরও বাস্তব-জীবন, অভিন্ন জিনিসগুলি আরও দূরে ছোট প্রদর্শিত হবে:

এখানে চিত্র বর্ণনা লিখুন

main.c

#include <stdlib.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

static int ortho = 0;

static void display(void) {
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    if (ortho) {
    } else {
        /* This only rotates and translates the world around to look like the camera moved. */
        gluLookAt(0.0, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    }
    glColor3f(1.0f, 1.0f, 1.0f);
    glutWireCube(2);
    glFlush();
}

static void reshape(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (ortho) {
        glOrtho(-2.0, 2.0, -2.0, 2.0, -1.5, 1.5);
    } else {
        glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
    }
    glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    if (argc > 1) {
        ortho = 1;
    }
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return EXIT_SUCCESS;
}

গিটহাব উজানের দিকে

সংকলন:

gcc -ggdb3 -O0 -o main -std=c99 -Wall -Wextra -pedantic main.c -lGL -lGLU -lglut

সাথে চালান glOrtho:

./main 1

সাথে চালান glFrustrum:

./main

উবুন্টু 18.10 এ পরীক্ষা করা হয়েছে।

স্কিমা

অর্থো: ক্যামেরাটি একটি বিমান, দৃশ্যমান ভলিউম একটি আয়তক্ষেত্র:

এখানে চিত্র বর্ণনা লিখুন

ফ্রাস্ট্রাম: ক্যামেরাটি একটি বিন্দু, দৃশ্যমান ভলিউম একটি পিরামিডের টুকরা:

এখানে চিত্র বর্ণনা লিখুন

চিত্র উত্স

পরামিতি

আমরা সর্বদা + z থেকে -z + y এর সাথে উপরের দিকে তাকিয়ে থাকি:

glOrtho(left, right, bottom, top, near, far)
  • left: ন্যূনতম xআমরা দেখতে পাই
  • right: সর্বাধিক xআমরা দেখতে
  • bottom: ন্যূনতম yআমরা দেখতে পাই
  • top: সর্বাধিক yআমরা দেখতে
  • -near: ন্যূনতম zআমরা দেখতে পাই। হ্যাঁ , এটি -1বার near। সুতরাং একটি নেতিবাচক ইনপুট মানে ধনাত্মক z
  • -far: সর্বাধিক zআমরা দেখতে। নেতিবাচকও।

স্কিমা:

চিত্র উত্স

এটি হুডের নীচে কীভাবে কাজ করে

শেষ পর্যন্ত ওপেনজিএল সর্বদা "ব্যবহার" করে:

glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);

আমরা যদি glOrthoনাও ব্যবহার glFrustrumকরি তবে তা আমরা পাই।

glOrthoএবং glFrustrumকেবল লিনিয়ার ট্রান্সফর্মেশনগুলি (একে একে ম্যাট্রিক্স গুণ) যেমন:

  • glOrtho: একটি প্রদত্ত 3D আয়তক্ষেত্রটি ডিফল্ট কিউবে নেয়
  • glFrustrum: প্রদত্ত পিরামিড বিভাগটি ডিফল্ট কিউবে নেয়

এই রূপান্তরটি তখন সমস্ত ভার্টেক্সে প্রয়োগ করা হয়। এটি আমি 2 ডি বলতে চাই:

চিত্র উত্স

রূপান্তরের পরে চূড়ান্ত পদক্ষেপটি সহজ:

  • ঘনক্ষেত্র কোন পয়েন্ট বাহিরে (কালিং) কে সরানো: শুধু নিশ্চিত হোন যে x, yএবং zহয়[-1, +1]
  • zউপাদানটিকে উপেক্ষা করুন এবং কেবল xএবং নিন y, যা এখন একটি 2 ডি স্ক্রিনে রাখা যেতে পারে

সহ glOrtho, zউপেক্ষা করা হয়, যাতে আপনি পাশাপাশি সর্বদা ব্যবহার করতে পারেন 0

আপনি যে কারণটি ব্যবহার করতে চাইতে পারেন তা z != 0হ'ল স্প্রেটসকে গভীরতা বাফারের সাথে পটভূমিটি আড়াল করা।

অবচয়

glOrthoওপেনজিএল 4.5 হিসাবে অবহিত করা হয়েছে : সামঞ্জস্যতা প্রোফাইল 12.1। "ফিক্সড-ফাংশন ভার্টেক্স ট্রান্সফর্মেশনস" লাল is

সুতরাং এটি উত্পাদন জন্য ব্যবহার করবেন না। যাই হোক না কেন, কিছু ওপেনজিএল অন্তর্দৃষ্টি পাওয়ার এটি ভাল উপায়।

আধুনিক ওপেনজিএল 4 প্রোগ্রাম সিপিইউতে রূপান্তর ম্যাট্রিক্স (যা ছোট) গণনা করে এবং তারপরে ম্যাট্রিক্স এবং সমস্ত পয়েন্টগুলি ওপেনগিএলে রূপান্তরিত করতে দেয়, যা বিভিন্ন পয়েন্টের জন্য হাজার হাজার ম্যাট্রিক্স গুণকে সত্যিই সমান্তরালে দ্রুত করতে পারে।

ম্যানুয়ালি লিখিত ভার্টেক্স শেডারগুলি তখন সাধারণত ওপেনএলএল শেডিং ল্যাঙ্গুয়েজের সুবিধার্থী ভেক্টর ডেটা ধরণের সাথে স্পষ্টভাবে গুণন করে।

যেহেতু আপনি ছাঁটা স্পষ্টভাবে লিখেন, এটি আপনাকে আপনার প্রয়োজন অনুসারে অ্যালগরিদমটি টুইঙ্ক করতে দেয়। এই জাতীয় নমনীয়তা আরও আধুনিক জিপিইউগুলির একটি প্রধান বৈশিষ্ট্য, যা পুরানোগুলির মতো নয় যা কিছু ইনপুট প্যারামিটারগুলির সাথে একটি নির্দিষ্ট অ্যালগরিদম করেছিল, এখন যথেচ্ছ গণনা করতে পারে। আরও দেখুন: https://stackoverflow.com/a/36211337/895245

স্পষ্টরূপে GLfloat transform[]এটি দেখতে এরকম কিছু দেখাবে:

glfw_transform.c

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define GLEW_STATIC
#include <GL/glew.h>

#include <GLFW/glfw3.h>

static const GLuint WIDTH = 800;
static const GLuint HEIGHT = 600;
/* ourColor is passed on to the fragment shader. */
static const GLchar* vertex_shader_source =
    "#version 330 core\n"
    "layout (location = 0) in vec3 position;\n"
    "layout (location = 1) in vec3 color;\n"
    "out vec3 ourColor;\n"
    "uniform mat4 transform;\n"
    "void main() {\n"
    "    gl_Position = transform * vec4(position, 1.0f);\n"
    "    ourColor = color;\n"
    "}\n";
static const GLchar* fragment_shader_source =
    "#version 330 core\n"
    "in vec3 ourColor;\n"
    "out vec4 color;\n"
    "void main() {\n"
    "    color = vec4(ourColor, 1.0f);\n"
    "}\n";
static GLfloat vertices[] = {
/*   Positions          Colors */
     0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
    -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
     0.0f,  0.5f, 0.0f, 0.0f, 0.0f, 1.0f
};

/* Build and compile shader program, return its ID. */
GLuint common_get_shader_program(
    const char *vertex_shader_source,
    const char *fragment_shader_source
) {
    GLchar *log = NULL;
    GLint log_length, success;
    GLuint fragment_shader, program, vertex_shader;

    /* Vertex shader */
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    glCompileShader(vertex_shader);
    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &log_length);
    log = malloc(log_length);
    if (log_length > 0) {
        glGetShaderInfoLog(vertex_shader, log_length, NULL, log);
        printf("vertex shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("vertex shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Fragment shader */
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    glCompileShader(fragment_shader);
    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = realloc(log, log_length);
        glGetShaderInfoLog(fragment_shader, log_length, NULL, log);
        printf("fragment shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("fragment shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Link shaders */
    program = glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = realloc(log, log_length);
        glGetProgramInfoLog(program, log_length, NULL, log);
        printf("shader link log:\n\n%s\n", log);
    }
    if (!success) {
        printf("shader link error");
        exit(EXIT_FAILURE);
    }

    /* Cleanup. */
    free(log);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    return program;
}

int main(void) {
    GLint shader_program;
    GLint transform_location;
    GLuint vbo;
    GLuint vao;
    GLFWwindow* window;
    double time;

    glfwInit();
    window = glfwCreateWindow(WIDTH, HEIGHT, __FILE__, NULL, NULL);
    glfwMakeContextCurrent(window);
    glewExperimental = GL_TRUE;
    glewInit();
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glViewport(0, 0, WIDTH, HEIGHT);

    shader_program = common_get_shader_program(vertex_shader_source, fragment_shader_source);

    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);
    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    /* Position attribute */
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    /* Color attribute */
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);
    glBindVertexArray(0);

    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shader_program);
        transform_location = glGetUniformLocation(shader_program, "transform");
        /* THIS is just a dummy transform. */
        GLfloat transform[] = {
            0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f,
        };
        time = glfwGetTime();
        transform[0] = 2.0f * sin(time);
        transform[5] = 2.0f * cos(time);
        glUniformMatrix4fv(transform_location, 1, GL_FALSE, transform);

        glBindVertexArray(vao);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glBindVertexArray(0);
        glfwSwapBuffers(window);
    }
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glfwTerminate();
    return EXIT_SUCCESS;
}

গিটহাব উজানের দিকে

সংকলন এবং চালান:

gcc -ggdb3 -O0 -o glfw_transform.out -std=c99 -Wall -Wextra -pedantic glfw_transform.c -lGL -lGLU -lglut -lGLEW -lglfw -lm
./glfw_transform.out

আউটপুট:

এখানে চিত্র বর্ণনা লিখুন

এর জন্য ম্যাট্রিক্সটি glOrthoখুব সহজ, কেবলমাত্র স্কেলিং এবং অনুবাদ দ্বারা রচিত:

scalex, 0,      0,      translatex,
0,      scaley, 0,      translatey,
0,      0,      scalez, translatez,
0,      0,      0,      1

উল্লেখিত হিসাবে যেমন OpenGL 2 ডক্স

glFrustumম্যাট্রিক্স হয় হ্যান্ড-নিরূপণ করা খুব কঠিন নয়, কিন্তু বিরক্তিকর পেয়ে শুরু হয়। কী পরিমাণ হতাশার সাথে শুধুমাত্র স্কেলিং এবং অনুবাদ যেমন glOrthoআরও তথ্যের জন্য প্রস্তুত করা যায় না তা এখানে নোট করুন : https://gamedev.stackexchange.com/a/118848/25171

জিএলএম ওপেনজিএল সি ++ গণিতের পাঠাগারটি এ জাতীয় ম্যাট্রিকগুলি গণনার জন্য একটি জনপ্রিয় পছন্দ। http://glm.g-truc.net/0.9.2/api/a00245.html একটি orthoএবং frustumঅপারেশন উভয়ই ডকুমেন্ট ।


4
"পরিবর্তে কী ব্যবহার করা উচিত?" - আপনার নিজের ম্যাট্রিক তৈরি করুন এবং তাদের সরাসরি বরাদ্দ করুন।
ক্রোমস্টার 13

আপনার শেষ কোড উদাহরণটি (ত্রিভুজ রূপান্তরকারী) সংকলন করতে আমার খুব কষ্ট হচ্ছে, আমি সংগ্রহস্থলটি ক্লোন করেছি কিন্তু আমি কেবল ত্রুটিটি common.h:19:23: error: ‘TIME_UTC’ undeclared (first use in this function) timespec_get(&ts, TIME_UTC);
পেয়েছি

4
@ ইভানজিনহো আমি উবুন্টু ২০.০৪-তে পুনরুত্পাদন করতে পারিনি, সম্ভবত ঘটছে কারণ এটি সি 11-এ রয়েছে যা আপনার জিসিসি এখনও কার্যকর করেনি। তবে এখন আমি এই উত্তরটির উদাহরণটিকে সাধারণ হিসাবে ছাড়িয়েছি .h যেমনটি আমার আগে করা উচিত ছিল তাই এটির কাজ করা উচিত :-)
সিওরো সান্তিলি 法轮功 冠状 病 六四 事件 事件 法轮功

4

glOrtho একটি রূপান্তর বর্ণনা করে যা একটি সমান্তরাল অভিক্ষেপ উত্পাদন করে । বর্তমান ম্যাট্রিক্স (দেখুন গ্লোম্যাট্রিক্সমোড) এই ম্যাট্রিক্স দ্বারা গুণিত হয়েছে এবং ফলাফলটি বর্তমান ম্যাট্রিক্সকে প্রতিস্থাপন করে, যেমন glMultMatrix তার আর্গুমেন্ট হিসাবে নিম্নলিখিত ম্যাট্রিক্সের সাথে ডাকা হয়েছিল:

ওপেনএল ডকুমেন্টেশন (আমার সাহসী)

নম্বরগুলি ক্লিপিং প্লেনগুলির অবস্থানগুলি নির্ধারণ করে (বাম, ডান, নীচে, শীর্ষ, কাছাকাছি এবং দূরে)।

"সাধারণ" অভিক্ষেপ একটি দৃষ্টিভঙ্গি প্রজেকশন যা গভীরতার মায়া সরবরাহ করে। উইকিপিডিয়া একটি সমান্তরাল প্রক্ষেপণ হিসাবে সংজ্ঞা দেয়:

সমান্তরাল প্রজেকশনগুলির প্রক্ষেপণের লাইন রয়েছে যা বাস্তবে এবং প্রক্ষেপণ বিমানের উভয়ই সমান্তরাল।

সমান্তরাল অভিক্ষেপ একটি অনুমানমূলক দৃষ্টিভঙ্গির সাথে একটি দৃষ্টিকোণ প্রক্ষেপণের সাথে সামঞ্জস্য করে — যেমন, যেখানে ক্যামেরাটি বস্তু থেকে এক অনন্ত দূরত্বে থাকে এবং একটি অসীম ফোকাল দৈর্ঘ্য বা "জুম" থাকে।


হাই তথ্য জন্য ধন্যবাদ। আমি সমান্তরাল এবং দৃষ্টিকোণ অভিক্ষেপের মধ্যে পার্থক্যটি বেশ বুঝতে পারি নি। আমি কিছুটা গুগল করেছিলাম
কিউ /

6
দুর্ভাগ্যক্রমে উত্তর ডটকম থেকে আপনি যে তথ্য পেয়েছেন তা বেশ মূল্যহীন। একটি আইসোমেট্রিক ভিউ, উদাহরণস্বরূপ, খুব 3-ডি, তবু এটি দৃষ্টিভঙ্গি ছাড়াই একটি সমান্তরাল প্রক্ষেপণ। এখানে দেখুন, এবং আরও অনেকগুলি অনুমানের উদাহরণের লিঙ্কগুলি রয়েছে: en.wikedia.org/wiki/Isometric_project
বেন ভয়েগট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.