2016-09-28 3 views
3

Mein Ziel ist es, 1 Million Kugeln in verschiedenen Größen und Farben mit 60 fps zu rendern. Ich möchte auch die Kamera um den Bildschirm bewegen können.Millionen Objekte in OpenGL instanziieren: Bilder pro Sekunde verbessern

Ich habe den Code auf this page of the tutorial I am studying geändert, um zu versuchen, viele Kugeln zu instanziieren. Ich finde jedoch, dass meine fps bei weniger als 64 Kugeln unter 60 fällt und bei 900 Kugeln meine fps eine mickrige 4. Mein Verständnis von Instanziierung ist naiv, aber ich glaube, dass ich mehr Frames pro Sekunde bekommen sollte als Dies. 60 fps sollten mit nur 64 Kugeln erreichbar sein. Ich glaube, dass ich irgendwie die CPU und die GPU dazu befähige, öfter zu kommunizieren, als sie sollten. Meine Frage ist also: Wie importiere ich so viele Objekte (idealerweise Millionen), ohne dass die fps tief fallen (idealerweise 60 fps)?

Ich berechne fps durch Berechnung von (10/time_elapsed) alle 10 Frames, wobei time_elapsed die Zeit ist, die seit dem letzten fps-Aufruf vergangen ist. Ich drucke dies unter Verwendung von printf in Zeile 118 meines Codes aus.

I wurde durch OpenGL this tutorial Lernen und so verwende ich 32-bit GLEW und 32-bit GLFW in Visual Studio 2013 Ich habe 8 GB RAM auf einem 64-Bit-Betriebssystem (Windows 7) mit einem 2.30 GHz CPU.

Ich habe versucht, mein eigenes Beispiel basierend auf dem obigen Tutorial zu programmieren. Quellcode:

(Legen Sie Zeile 2 als die Anzahl der zu instanzierenden Kugeln fest. Stellen Sie sicher, dass Zeile 2 eine ganzzahlige Quadratwurzel aufweist. Legen Sie Linie 4 als Detail der Kugel fest, die niedrigste go ist 0. Höhere Zahl = detaillierteren)

// Make sure NUM_INS is a square number 
#define NUM_INS 1 

// Detail up to 4 is probably good enough 
#define SPHERE_DETAIL 4 

#include <vector> 

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

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

// GL includes 
#include "Shader.h" 

// GLM Mathemtics 
#include <glm/glm.hpp> 
#include <glm/gtc/matrix_transform.hpp> 
#include <glm/gtc/type_ptr.hpp> 

// Properties 
GLuint screenWidth = 800, screenHeight = 600; 

// Function prototypes 
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); 
std::vector<GLfloat> create_sphere(int recursion); 

// The MAIN function, from here we start our application and run the Game loop 
int main() 
{ 
    // Init GLFW 
    glfwInit(); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); 

    GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed 
    glfwMakeContextCurrent(window); 

    // Set the required callback functions 
    glfwSetKeyCallback(window, key_callback); 

    // Initialize GLEW to setup the OpenGL Function pointers 
    glewExperimental = GL_TRUE; 
    glewInit(); 

    // Define the viewport dimensions 
    glViewport(0, 0, screenWidth, screenHeight); 
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Comment to remove wireframe mode 

    // Setup OpenGL options 
    glEnable(GL_DEPTH_TEST); 

    // Setup and compile our shader(s) 
    Shader shader("core.vs", "core.frag"); 

    // Generate a list of 100 quad locations/translation-vectors 
    std::vector<glm::vec2> translations(NUM_INS); 
    //glm::vec2 translations[NUM_INS]; 
    int index = 0; 
    GLfloat offset = 1.0f/(float)sqrt(NUM_INS); 
    for (GLint y = -(float)sqrt(NUM_INS); y < (float)sqrt(NUM_INS); y += 2) 
    { 
    for (GLint x = -(float)sqrt(NUM_INS); x < (float)sqrt(NUM_INS); x += 2) 
    { 
     glm::vec2 translation; 
     translation.x = (GLfloat)x/(float)sqrt(NUM_INS) + offset; 
     translation.y = (GLfloat)y/(float)sqrt(NUM_INS) + offset; 
     translations[index++] = translation; 
    } 
    } 

    // Store instance data in an array buffer 
    GLuint instanceVBO; 
    glGenBuffers(1, &instanceVBO); 
    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * NUM_INS, &translations[0], GL_STATIC_DRAW); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    // create 12 vertices of a icosahedron 
    std::vector<GLfloat> vv = create_sphere(SPHERE_DETAIL); 

    GLuint quadVAO, quadVBO; 
    glGenVertexArrays(1, &quadVAO); 
    glGenBuffers(1, &quadVBO); 
    glBindVertexArray(quadVAO); 
    glBindBuffer(GL_ARRAY_BUFFER, quadVBO); 
    glBufferData(GL_ARRAY_BUFFER, vv.size() * sizeof(GLfloat), &vv[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); 
    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat))); 
    // Also set instance data 
    glEnableVertexAttribArray(2); 
    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glVertexAttribDivisor(2, 1); // Tell OpenGL this is an instanced vertex attribute. 
    glBindVertexArray(0); 

    // For printing frames-per-second 
    float counter = 0; 
    double get_time = 0; 
    double new_time; 

    // Game loop 
    while (!glfwWindowShouldClose(window)) 
    { 
    // Print fps by printing (number_of_frames/time_elapsed) 
    counter += 1; 
    if (counter > 10) { 
     counter -= 10; 
     new_time = glfwGetTime(); 
     printf("fps: %.2f ", (10/(new_time - get_time))); 
     get_time = new_time; 
    } 

    // Check and call events 
    glfwPollEvents(); 

    // Clear buffers 
    //glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    // Draw 100 instanced quads 
    shader.Use(); 

    glm::mat4 model; 
    model = glm::rotate(model, 0.0f, glm::vec3(1.0f, 0.0f, 0.0f)); 
    // Camera/View transformation 
    glm::mat4 view; 
    GLfloat radius = 10.0f; 
    GLfloat camX = sin(glfwGetTime()) * radius; 
    GLfloat camZ = cos(glfwGetTime()) * radius; 
    view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); 
    // Projection 
    glm::mat4 projection; 
    projection = glm::perspective(45.0f, (GLfloat)screenWidth/(GLfloat)screenHeight, 0.1f, 100.0f); 
    // Get the uniform locations 
    GLint modelLoc = glGetUniformLocation(shader.Program, "model"); 
    GLint viewLoc = glGetUniformLocation(shader.Program, "view"); 
    GLint projLoc = glGetUniformLocation(shader.Program, "projection"); 
    // Pass the matrices to the shader 
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); 
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); 
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); 

    glBindVertexArray(quadVAO); 
    glDrawArraysInstanced(GL_TRIANGLES, 0, vv.size()/3, NUM_INS); // 100 triangles of 6 vertices each 
    glBindVertexArray(0); 

    // Swap the buffers 
    glfwSwapBuffers(window); 
    } 

    glfwTerminate(); 
    return 0; 
} 

// Is called whenever a key is pressed/released via GLFW 
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) 
{ 
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) 
    glfwSetWindowShouldClose(window, GL_TRUE); 
} 

std::vector<GLfloat> add_color(std::vector<GLfloat> sphere) { 
    // Add color 
    std::vector<GLfloat> colored_sphere; 
    for (GLint i = 0; i < sphere.size(); i+=9) { 
    colored_sphere.push_back(sphere[i]); 
    colored_sphere.push_back(sphere[i+1]); 
    colored_sphere.push_back(sphere[i+2]); 
    colored_sphere.push_back(0.0f); 
    colored_sphere.push_back(0.0f); 
    colored_sphere.push_back(0.0f); 
    colored_sphere.push_back(sphere[i+3]); 
    colored_sphere.push_back(sphere[i+4]); 
    colored_sphere.push_back(sphere[i+5]); 
    colored_sphere.push_back(0.0f); 
    colored_sphere.push_back(0.0f); 
    colored_sphere.push_back(0.0f); 
    colored_sphere.push_back(sphere[i+6]); 
    colored_sphere.push_back(sphere[i+7]); 
    colored_sphere.push_back(sphere[i+8]); 
    colored_sphere.push_back(0.0f); 
    colored_sphere.push_back(0.0f); 
    colored_sphere.push_back(0.0f); 
    } 

    return colored_sphere; 
} 

std::vector<GLfloat> tesselate(std::vector<GLfloat> shape, int recursion) { 

    if (recursion > 0) { 
    std::vector<GLfloat> new_sphere = {}; 
    for (GLint i = 0; i < shape.size(); i += 9) { 

     // 1.902113 approximately 
     GLfloat radius = sqrt(1.0f + pow((1.0f + sqrt(5.0f))/2.0f, 2)); 

     // Every 9 points is a triangle. Take 1 triangle and turn it into 4 triangles. 
     GLfloat p_one[] = {shape[i], shape[i + 1], shape[i + 2]}; 
     GLfloat p_two[] = {shape[i + 3], shape[i + 4], shape[i + 5]}; 
     GLfloat p_thr[] = {shape[i + 6], shape[i + 7], shape[i + 8]}; 
     GLfloat p_one_two[] = { (p_one[0] + p_two[0])/2.0f, (p_one[1] + p_two[1])/2.0f, (p_one[2] + p_two[2])/2.0f }; 
     GLfloat p_one_thr[] = { (p_one[0] + p_thr[0])/2.0f, (p_one[1] + p_thr[1])/2.0f, (p_one[2] + p_thr[2])/2.0f }; 
     GLfloat p_two_thr[] = { (p_two[0] + p_thr[0])/2.0f, (p_two[1] + p_thr[1])/2.0f, (p_two[2] + p_thr[2])/2.0f }; 

     GLfloat r_one_two = sqrt((p_one_two[0]*p_one_two[0]) + (p_one_two[1]*p_one_two[1]) + (p_one_two[2]*p_one_two[2])); 
     GLfloat r_one_thr = sqrt((p_one_thr[0]*p_one_thr[0]) + (p_one_thr[1]*p_one_thr[1]) + (p_one_thr[2]*p_one_thr[2])); 
     GLfloat r_two_thr = sqrt((p_two_thr[0]*p_two_thr[0]) + (p_two_thr[1]*p_two_thr[1]) + (p_two_thr[2]*p_two_thr[2])); 

     GLfloat t_one_two[] = { radius * p_one_two[0]/r_one_two, radius * p_one_two[1]/r_one_two, radius * p_one_two[2]/r_one_two }; 
     GLfloat t_one_thr[] = { radius * p_one_thr[0]/r_one_thr, radius * p_one_thr[1]/r_one_thr, radius * p_one_thr[2]/r_one_thr }; 
     GLfloat t_two_thr[] = { radius * p_two_thr[0]/r_two_thr, radius * p_two_thr[1]/r_two_thr, radius * p_two_thr[2]/r_two_thr }; 

     // Triangle 1: 
     new_sphere.push_back(p_one[0]); 
     new_sphere.push_back(p_one[1]); 
     new_sphere.push_back(p_one[2]); 

     new_sphere.push_back(t_one_two[0]); 
     new_sphere.push_back(t_one_two[1]); 
     new_sphere.push_back(t_one_two[2]); 

     new_sphere.push_back(t_one_thr[0]); 
     new_sphere.push_back(t_one_thr[1]); 
     new_sphere.push_back(t_one_thr[2]); 

     // Triangle 2: 
     new_sphere.push_back(p_two[0]); 
     new_sphere.push_back(p_two[1]); 
     new_sphere.push_back(p_two[2]); 

     new_sphere.push_back(t_one_two[0]); 
     new_sphere.push_back(t_one_two[1]); 
     new_sphere.push_back(t_one_two[2]); 

     new_sphere.push_back(t_two_thr[0]); 
     new_sphere.push_back(t_two_thr[1]); 
     new_sphere.push_back(t_two_thr[2]); 

     // Triangle 3: 
     new_sphere.push_back(p_thr[0]); 
     new_sphere.push_back(p_thr[1]); 
     new_sphere.push_back(p_thr[2]); 

     new_sphere.push_back(t_one_thr[0]); 
     new_sphere.push_back(t_one_thr[1]); 
     new_sphere.push_back(t_one_thr[2]); 

     new_sphere.push_back(t_two_thr[0]); 
     new_sphere.push_back(t_two_thr[1]); 
     new_sphere.push_back(t_two_thr[2]); 

     // Center Triangle: 

     new_sphere.push_back(t_one_two[0]); 
     new_sphere.push_back(t_one_two[1]); 
     new_sphere.push_back(t_one_two[2]); 

     new_sphere.push_back(t_one_thr[0]); 
     new_sphere.push_back(t_one_thr[1]); 
     new_sphere.push_back(t_one_thr[2]); 

     new_sphere.push_back(t_two_thr[0]); 
     new_sphere.push_back(t_two_thr[1]); 
     new_sphere.push_back(t_two_thr[2]); 
    } 
    return tesselate(new_sphere, recursion - 1); 
    } 

    printf("number of vertices to be rendered: %d || ", shape.size()); 
    return shape; 
} 

std::vector<GLfloat> create_sphere(int recursion) { 

    // Define the starting icosahedron 
    GLfloat t_ = (1.0f + sqrt(5.0f))/2.0f; 

    std::vector<GLfloat> icosahedron = { 
    -1.0f, t_, 0.0f, -t_, 0.0f, 1.0f, 0.0f, 1.0f, t_, 
    -1.0f, t_, 0.0f, 0.0f, 1.0f, t_, 1.0f, t_, 0.0f, 
    -1.0f, t_, 0.0f, 1.0f, t_, 0.0f, 0.0f, 1.0f, -t_, 
    -1.0f, t_, 0.0f, 0.0f, 1.0f, -t_, -t_, 0.0f, -1.0f, 
    -1.0f, t_, 0.0f, -t_, 0.0f, -1.0f, -t_, 0.0f, 1.0f, 

    1.0f, t_, 0.0f, 0.0f, 1.0f, t_, t_, 0.0f, 1.0f, 
    0.0f, 1.0f, t_, -t_, 0.0f, 1.0f, 0.0f, -1.0f, t_, 
    -t_, 0.0f, 1.0f, -t_, 0.0f, -1.0f, -1.0f, -t_, 0.0f, 
    -t_, 0.0f, -1.0f, 0.0f, 1.0f, -t_, 0.0f, -1.0f, -t_, 
    0.0f, 1.0f, -t_, 1.0f, t_, 0.0f, t_, 0.0f, -1.0f, 

    1.0f, -t_, 0.0f, t_, 0.0f, 1.0f, 0.0f, -1.0f, t_, 
    1.0f, -t_, 0.0f, 0.0f, -1.0f, t_,-1.0f, -t_, 0.0f, 
    1.0f, -t_, 0.0f,-1.0f, -t_, 0.0f, 0.0f, -1.0f, -t_, 
    1.0f, -t_, 0.0f, 0.0f, -1.0f, -t_, t_, 0.0f, -1.0f, 
    1.0f, -t_, 0.0f, t_, 0.0f, -1.0f, t_, 0.0f, 1.0f, 

    0.0f, -1.0f, t_, t_, 0.0f, 1.0f, 0.0f, 1.0f, t_, 
    -1.0f, -t_, 0.0f, 0.0f, -1.0f, t_,-t_, 0.0f, 1.0f, 
    0.0f, -1.0f, -t_,-1.0f, -t_, 0.0f,-t_, 0.0f, -1.0f, 
    t_, 0.0f, -1.0f, 0.0f, -1.0f, -t_, 0.0f, 1.0f, -t_, 
    t_, 0.0f, 1.0f, t_, 0.0f, -1.0f, 1.0f, t_, 0.0f, 
    }; 

    // Tesselate the icososphere the number of times recursion 
    std::vector<GLfloat> colorless_sphere = tesselate(icosahedron, recursion); 

    // Add color and return 
    return add_color(colorless_sphere); 
} 

Vertex Shader:. (benannt core.vs)

#version 330 core 
layout (location = 0) in vec3 position; 
layout (location = 1) in vec3 color; 
layout (location = 2) in vec2 offset; 

out vec3 fColor; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 

void main() 
{ 
    gl_Position = projection * view * model * vec4(position.x + offset.x, position.y + offset.y, position.z, 1.0f); 
    fColor = color; 
} 

Fragment Shader: (benannt core.frag)

#version 330 core 
in vec3 fColor; 
out vec4 color; 

void main() 
{ 
    color = vec4(fColor, 1.0f); 
} 

Shader-Klasse: (benannt Shader.h)

#ifndef SHADER_H 
#define SHADER_H 

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

#include <GL/glew.h> 

class Shader 
{ 
    public: 
    GLuint Program; 
    // Constructor generates the shader on the fly 
    Shader(const GLchar* vertexPath, const GLchar* fragmentPath) 
    { 
    // 1. Retrieve the vertex/fragment source code from filePath 
    std::string vertexCode; 
    std::string fragmentCode; 
    std::ifstream vShaderFile; 
    std::ifstream fShaderFile; 
    // ensures ifstream objects can throw exceptions: 
     vShaderFile.exceptions(std::ifstream::badbit); 
    fShaderFile.exceptions(std::ifstream::badbit); 
    try 
    { 
     // Open files 
     vShaderFile.open(vertexPath); 
     fShaderFile.open(fragmentPath); 
     std::stringstream vShaderStream, fShaderStream; 
     // Read file's buffer contents into streams 
     vShaderStream << vShaderFile.rdbuf(); 
     fShaderStream << fShaderFile.rdbuf(); 
     // close file handlers 
     vShaderFile.close(); 
     fShaderFile.close(); 
     // Convert stream into string 
     vertexCode = vShaderStream.str(); 
     fragmentCode = fShaderStream.str(); 
    } 
     catch (std::ifstream::failure e) 
     { 
     std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; 
     } 
     const GLchar* vShaderCode = vertexCode.c_str(); 
     const GLchar * fShaderCode = fragmentCode.c_str(); 
     // 2. Compile shaders 
     GLuint vertex, fragment; 
     GLint success; 
     GLchar infoLog[512]; 
     // Vertex Shader 
     vertex = glCreateShader(GL_VERTEX_SHADER); 
     glShaderSource(vertex, 1, &vShaderCode, NULL); 
     glCompileShader(vertex); 
     // Print compile errors if any 
     glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); 
     if (!success) 
     { 
     glGetShaderInfoLog(vertex, 512, NULL, infoLog); 
     std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; 
     } 
     // Fragment Shader 
     fragment = glCreateShader(GL_FRAGMENT_SHADER); 
     glShaderSource(fragment, 1, &fShaderCode, NULL); 
     glCompileShader(fragment); 
     // Print compile errors if any 
     glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); 
     if (!success) 
     { 
     glGetShaderInfoLog(fragment, 512, NULL, infoLog); 
     std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; 
     } 
     // Shader Program 
     this->Program = glCreateProgram(); 
     glAttachShader(this->Program, vertex); 
     glAttachShader(this->Program, fragment); 
     glLinkProgram(this->Program); 
     // Print linking errors if any 
     glGetProgramiv(this->Program, GL_LINK_STATUS, &success); 
     if (!success) 
     { 
     glGetProgramInfoLog(this->Program, 512, NULL, infoLog); 
     std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; 
     } 
     // Delete the shaders as they're linked into our program now and no longer necessery 
     glDeleteShader(vertex); 
     glDeleteShader(fragment); 

    } 
    // Uses the current shader 
    void Use() 
    { 
     glUseProgram(this->Program); 
    } 
}; 

#endif 
+0

wahrscheinlich unbedeutend, aber Sie könnten '(float) sqrt (NUM_INS)' ein für alle Mal berechnen (die CPU wird Danke sagen). –

+0

dies half med instanced rendering: http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html Es ist nur eine andere Zeichnungsaufruf, der die GPU angewiesen, bereits gesendete Informationen zu recyceln – Charlie

+0

Welche Klasse von Hardware zielen Sie aus Neugier? Sie können immer die Gelegenheit nutzen, um über Compute Shader und indirektes Zeichnen zu lernen :) Generieren Sie alle diese Instanzen komplett GPU-Seite und die Dinge werden fliegen. –

Antwort

4

Mein Ziel ist eine Million Kugeln in verschiedenen Größen und Farben bei 60 Bildern pro Sekunde zu machen.

Dies ist eine unangemessene Erwartung.

Sagen wir, jede Kugel besteht aus 50 Dreiecken. Ein bisschen klein für eine gute Kugelform, aber nehmen wir an, sie sind so klein.

1 Million Kugeln bei 50 Tris pro Kugel sind 50 Millionen Dreiecke pro Rahmen. Bei 60 fps ist das 3 Milliarden Dreiecke pro Sekunde.

Keine kommerziell verfügbare GPU ist gut genug, um das zu tun. Und das ist nur eine 50-Dreieck-Kugel; Ihr 4x tessellated Ikosaeder wird über 5.000 Dreiecke sein.

Nun ja, Zeichnung 60 solcher Kugeln ist nur ~ 300.000 Dreiecke pro Rahmen. Aber selbst das bei 60 fps ist ~ 18 Millionen Dreiecke pro Sekunde. Hardware existiert, die mit so vielen Dreiecken umgehen kann, aber es ist sehr deutlich ein Los.Und du bist definitiv werde nicht 1 Million von ihnen bekommen.

Dies ist keine Frage der GPU/CPU-Kommunikation oder Overhead. Sie werfen einfach mehr Arbeit an Ihre GPU, als sie verarbeiten könnte. Vielleicht könntest du hier und da ein paar Dinge verbessern, aber nichts, was dir ein Zehntel von dem bringt, was du willst.

Zumindest nicht mit diesem Gesamtansatz.


Für Ihren besonderen Fall wollen Millionen von Kugeln zu ziehen, würde ich Raytracing-Betrüger eher als die tatsächliche Geometrie der Kugeln verwenden. Das heißt, Sie zeichnen Quads, deren Positionen vom Scheitelpunkt- (oder Geometrie-) Shader generiert werden. Sie erzeugen ein Quad pro Kugel, so dass das Quad die Kugel umschreibt. Dann führt der Fragment-Shader einen einfachen Strahl-Kugel-Schnitt-Test durch, um zu sehen, ob das fragliche Fragment (aus der Richtung der Kameraansicht) die Kugel trifft oder nicht. Wenn der Strahl die Kugel nicht trifft, wirf das Fragment ab.

Sie müssten auch gl_FragDepth ändern, um dem Betrüger den richtigen Tiefenwert zu geben, damit sich überschneidende Kugeln arbeiten können.

+0

Vielleicht hast du Recht, dass Millionen von Bereichen zu ehrgeizig ist. Aber hier ist ein Video, wo eine halbe Million Kugeln in OpenGL gerendert werden, wo sie sich bewegen und stopfen: https://www.youtube.com/watch?v=Tnc_IoXwH24 Vielleicht muss ich mein Projekt ändern, um Ihre Kriterien zu erfüllen oder eine niedrigere fps wie in diesem Video. –

+0

@PaulTerwilliger: Hast du die Details zu diesem Video gelesen? Insbesondere der Teil, wo es heißt "Die Anzahl der Dreiecke für jede Kugel hängt von der Entfernung vom Betrachter ab." Das heißt, Instanziierung als Werkzeug. –

+0

Ich sehe, also gibt es keine Möglichkeit, dass Sie Instantiierung für verschiedene Details von Kugeln verwenden? Konnte ich keine Kugeln verschiedener Details an die GPU senden und dann einige oder andere abhängig von der Entfernung rendern? –

Verwandte Themen