• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem ze zrozumienie kodu w OpenGL.

Object Storage Arubacloud
0 głosów
190 wizyt
pytanie zadane 18 lipca 2020 w OpenGL, Unity przez tonn204 Mądrala (7,440 p.)

Cześć mam problem ze zrozumieniem kodu. Mianowicie skąd OpenGL wie, które liczby traktować jako punkty na osiach X i Y, a które jako kolory [patrz vertices]? Co się dzieje kiedy  w glVertexAttribPointer pierwszy argument ma wartość 1 i co to oznacza, bo w docs.gl pisze o jakimś index, ale nie rozumiem o jaki index chodzi. O co chodzi  w glVertexAttribPointer, gdy pierwszy argument utawiony jest na 1 i dlaczego ostatni ustawiony jest na (void*)(3 * sizeof(float) i co te argumenty oznaczają? Dzięki za odpowiedzi.

 

 

Plik główny:

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include <fstream>
#include <string>

static unsigned int CompileShader(unsigned int type, std::string source)
{
    unsigned int id = glCreateShader(type);
    const char* src = source.c_str();
    glShaderSource(id, 1, &src, nullptr);
    glCompileShader(id);

    int result;
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);
    if (result == GL_FALSE)
    {
        int length;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); 
        char* message = (char*)_malloca(length * sizeof(char));
        glGetShaderInfoLog(id, length, &length, message);
        std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader" << std::endl;
        std::cout << message << std::endl;
        glDeleteShader(id);

        return 0;

    }

    return id;
}

static unsigned int CreateShader(const std::string& vertexShader, const std::string fragmentShader)
{
    unsigned int program = glCreateProgram();
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    glAttachShader(program, vs);
    glAttachShader(program, fs);
    glLinkProgram(program);

    glDeleteShader(vs);
    glDeleteShader(fs);

    return program;
}

std::string readFromFile(const char* pathToFile)
{
    std::string content;
    std::ifstream fileStream(pathToFile, std::ios::in);

    if (!fileStream.is_open()) {
        std::cerr << "Could not read file " << pathToFile << ". File does not exist." << std::endl;
        return "";
    }

    std::string line;
    while (std::getline(fileStream, line)) {
        content.append(line + "\n");
    }

    fileStream.close();
    std::cout << content << std::endl;
    return content;
}
int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);
    //glfwSwapInterval(1);           // Update a scene per "x" frames.

    if (glewInit() != GLEW_OK)
        std::cout << "Error" << std::endl;

    std::cout << glGetString(GL_VERSION) << std::endl;
    
    float vertices[] = {
        // positions            // Colors
        0.0f,  0.5f, 0.0f,      1.0f, 0.0f, 0.0f, // bottom right
       -0.5f, -0.5f, 0.0f,      0.0f, 1.0f, 0.0f, // bottom left
        0.5f, -0.5f, 0.0f,      0.0f, 0.0f, 1.0f  // top
    };

    unsigned int VBO;

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    std::string vertexShaderSource = readFromFile("vertexShader.shader");
    std::string fragmentShaderSource = readFromFile("fragmentShader.shader");

    unsigned int shaderProgram = CreateShader(vertexShaderSource, fragmentShaderSource);

    int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {

        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);

        glDrawArrays(GL_TRIANGLES, 0, 3);
        
        float timeValue = glfwGetTime();
        float greenValue = sin(timeValue) / 2.0f + 0.5f;

        glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

Vertex shader:

#version 330 core
layout(location = 0) in vec3 aPos;   // the position variable has attribute position 0
layout(location = 1) in vec3 aColor; // the color variable has attribute position 1

out vec3 ourColor; // output a color to the fragment shader

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor; // set ourColor to the input color we got from the vertex data
}

Fragment shader:

#version 330 core
out vec4 FragColor;
in vec3 ourColor;

void main()
{
    FragColor = vec4(ourColor, 1.0);
}

 

2 odpowiedzi

+1 głos
odpowiedź 19 lipca 2020 przez Patrycjerz Mędrzec (192,320 p.)
wybrane 19 lipca 2020 przez tonn204
 
Najlepsza
Funkcja `glVertexAttribPointer` definiuje, w jaki sposób dane atrybutów wierzchołków są przechowywane w buforze.

Jej pierwszym argumentem jest indeks, który umożliwia powiązanie definicji atrybutu ze zmienną wejściową shadera wierzchołków. Np. atrybut koordynatów wierzchołka ma indeks równy 0, zaś w kodzie shadera zmienna `aPos` ma taki indeks ustawiony w `layout(location = 0)`. Analogiczna sytuacja występuje w przypadku zmiennej `aColor`, która ma przypisany indeks o wartości 1.

Ostatni argument funkcji to początkowe przesunięcie. Aby zdefiniować atrybut, potrzebujesz wiedzieć, gdzie w pamięci bufora zaczyna się jego pierwsze wystąpienie. Pierwszy zestaw koordynatów wierzchołka znajduje się na początku bufora, zaś pierwszy zestaw wartości kolorów dopiero po tych trzech współrzędnych. Definiujesz to jako `(void*)(3 * sizeof(float))`, czyli potrójny rozmiar pojedynczego koordynatu. Moim zdaniem lepiej używać typedefu `GLfloat`, który bezpośrednio odpowiada `GL_FLOAT`, zamiast typu `float`, ale w przypadku kompilacji na x86 nie powinno to robić większej różnicy.
komentarz 19 lipca 2020 przez tonn204 Mądrala (7,440 p.)
Wielkie dzięki !
+1 głos
odpowiedź 19 lipca 2020 przez adrian17 Ekspert (344,860 p.)

Polecam ten poradnik:

https://learnopengl.com/Getting-started/Hello-Triangle

https://learnopengl.com/Getting-started/Shaders

pierwszy argument ma wartość 1 i co to oznacza, bo w docs.gl pisze o jakimś index, ale nie rozumiem o jaki index chodzi

Z pierwszego linku:

  • The first parameter specifies which vertex attribute we want to configure. Remember that we specified the location of the position vertex attribute in the vertex shader with layout (location = 0). This sets the location of the vertex attribute to 0 and since we want to pass data to this vertex attribute, we pass in 0.

dlaczego ostatni ustawiony jest na (void*)(3 * sizeof(float) 

A to wyjaśnia ta część z drugiego linku:

Podobne pytania

0 głosów
1 odpowiedź 236 wizyt
pytanie zadane 1 sierpnia 2020 w OpenGL, Unity przez tonn204 Mądrala (7,440 p.)
0 głosów
1 odpowiedź 101 wizyt
0 głosów
0 odpowiedzi 103 wizyt
pytanie zadane 14 lipca 2020 w OpenGL, Unity przez tonn204 Mądrala (7,440 p.)

92,579 zapytań

141,429 odpowiedzi

319,657 komentarzy

61,962 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...