Есть ли способ использовать сложные/производные классы в GLSL?

В своих проектах OpenGL я никогда не использовал пользовательские структуры в шейдерах GLSL. До сих пор я прекрасно справлялся с массивами mat4,vec4,int. В моем последнем проекте я рассматриваю возможность добавления поддержки системы с несколькими источниками света. Опять же, когда это требовалось, я просто использовал отдельные массивы для положения источников света, цветов и так далее. Это явно не удобно, но с учетом масштаба моих прошлых приложений этого было достаточно.

В моем последнем проекте, однако, я думаю, что мне придется немного больше организовывать свои данные, потому что массивы абсолютно не так управляемы, но и не так уж расходуемы. Итак, я знаю, что GLSL поддерживает структуры, но проблема в том, что в моем основном коде есть гораздо более «сложные» классы с данными, которые мне не нужны в шейдере GLSL. Например, это мой основной класс освещения, который на самом деле является производным от очень простого класса модели:

public class Model
{
    public string name;
    public Vector3 position;
    public Matrix4 rotationMatrix;
    //Many more attributes and properties related to the GUI
}


public class Light: Model
{
    public Vector3 color;
    public Vector3 ambient;
    public float intensity;
    public float specular;
}

Учитывая эту структуру данных, я совершенно не понимаю, как использовать ее непосредственно в шейдерах GLSL. Так что мое решение на данный момент состоит в том, чтобы предоставить упрощенную версию класса в виде структуры, которая содержит только необходимую информацию, которая мне нужна в шейдерах. Это не звучит хорошим решением, потому что мне придется практически поддерживать 2 версии для всех моих разных классов моделей.

public struct SimpleLightStruct
{
    public Vector4 position;
    public Vector3 color;
    public Vector3 ambient;
    public float intensity;
    public float specular;
}

Итак, мой вопрос: является ли это решение единственным вариантом? Как более продвинутые разработчики игр организуют свои данные?

Поскольку я использую графический интерфейс для изменения свойств объекта, мне нужно каким-то образом добавить свойства практически ко всем моим классам данных, и это лишает всю простоту классов, я, очевидно, не могу учитывать размеры классов для OpenGL. обратные вызовы, но даже если бы у меня не было дополнительных свойств, даже поле имени запрещало бы мне использовать общую структуру для обоих целей.


person Greg K.    schedule 17.06.2019    source источник
comment
Есть ли способ использовать сложные/производные классы в GLSL? - краткий ответ: нет.   -  person Rabbid76    schedule 17.06.2019
comment
@Rabbid76, значит, иметь 2 версии для одного и того же класса — единственный способ?   -  person Greg K.    schedule 17.06.2019
comment
gsl не поддерживает классы. В gsl есть структуры, вот и все. См. Спецификацию OpenGL Shading Language 4.60. - 4.1.12. Структуры, стр. 33   -  person Rabbid76    schedule 17.06.2019
comment
@GregK.: Я совершенно не понимаю, как использовать это непосредственно в шейдерах GLSL. Вы не можете. Вы объявили его как class, поэтому вы не можете просто передать его C API, такому как OpenGL.   -  person Nicol Bolas    schedule 17.06.2019
comment
@NicolBolas Вот что я пытаюсь здесь подчеркнуть. Даже если бы я использовал структуры, скажем, со строковыми полями, смог бы я использовать структуру напрямую?   -  person Greg K.    schedule 17.06.2019
comment
@GregK. Что вы подразумеваете под использовать структуру напрямую? Как вы думаете, можно ли каким-то волшебным образом установить значения некоторых переменных, которые используются в шейдере, с помощью оператора присваивания C#?   -  person Rabbid76    schedule 17.06.2019
comment
@Rabbid76: Я полагаю, вставив его в буферный объект.   -  person Nicol Bolas    schedule 17.06.2019


Ответы (1)


C (и, следовательно, OpenGL) не говорит на C#. Он говорит только на очень маленьком подмножестве C#. Так что при взаимодействии с C API вы должны придерживаться именно этого.

Вы выполняете маршалинг данных из C# в C API, поэтому для этого необходимо следовать правилам. Обычно это означает, что если вы хотите просто скопировать какой-либо объект непосредственно в память C API, вам нужно придерживаться только тех типов структур C#, которые имеют аналоги C.

Как именно вы это сделаете, зависит от вас. Вы можете хранить свои данные на С#, как хотите, а затем копировать их во временный объект для пересылки в объект буфера OpenGL. Или вы можете хранить массив структур C, параллельный световым данным C#, с вашими данными C#, имеющими индекс структуры C, которой они соответствуют. Или другие вещи.

person Nicol Bolas    schedule 17.06.2019
comment
Итак, насколько я понимаю, нет никакого показательного способа делать такие вещи. Опять же, программист должен решить, какой подход является лучшим. Это примерно то, что я хотел знать. Спасибо - person Greg K.; 17.06.2019