Форум программистов, компьютерный форум, киберфорум
Наши страницы

Пишу игровой движок на C++. 018. Материал, текстура, шейдер, рисование 2D картинки - основы.

Войти
Регистрация
Восстановить пароль
Исходные коды движка - https://github.com/532235/GoST
Документация

Другой хобби-проект в группе в вк https://vk.com/club154291467
Рейтинг: 2.00. Голосов: 1.

Пишу игровой движок на C++. 018. Материал, текстура, шейдер, рисование 2D картинки - основы.

Запись от 532235 размещена 15.12.2017 в 13:07

Когда рисуется объект, рисуется трёхмерная сетка, посылая всего навсего массив координат расположения точек в 3d пространстве.
Для того чтобы объект рисовался с наложенной на него картинкой, с настроенными параметрами (напр. уровень отражения света, блеск, цвет тени, и многое другое), нужно сделать ряд установок, например, установить шейдер, установить текстуру, установит параметры шейдера, установить параметры рисования (типа рисовать заднюю грань или нет).
Проще всего создать структуру которая будет хранить все эти значения.

Опишу всё что придёт голову. Использоваться будет не сразу всё, это зависит от шейдера.
gtMaterial.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#pragma once
#ifndef __GT_MATERIAL_H__
#define __GT_MATERIAL_H__
 
/*
*/
 
namespace gost{
 
 
    //  Тип операции смешевания.
    enum gtMaterialBlendOp : u32 {
 
            //  Result = Source + Destination
        BOP_ADD,
            
            //  Result = Source - Destination
        BOP_SUBSTRACT,
 
            //  Result = Destination - Source
        BOP_SUBSTRACT_REVERSE,
 
            //  минимальное из Destination Source
        BOP_MIN,
 
            //  максимальное из Destination Source
        BOP_MAX
    };
 
        //  флаги
    enum gtMaterialFlag : u32 {
 
        //  рисовать только сетку
        MF_WIREFRAME = 1u,
 
        //  рисовать заднюю грань
        MF_BACKFACE = 2u,
        
        //  рисовать ли объект с прозрачностью
        MF_BLEND = 4u,
 
        //  не отбрасывать тень
        MF_NOCASTSHADOW = 8u,
 
        //  не получать тень
        MF_NORECEIVESHADOW = 16u,
 
        //  не получать тень от самого себя
        MF_NOSELFSHADOW = 32u
 
    };
 
        //  параметры для каждой текстуры
    struct gtMaterialTextureLayer{
 
        gtMaterialTextureLayer( void ):
            diffuseColor( 1.f ),
            blendOperation( gtMaterialBlendOp::BOP_SUBSTRACT ),
            level( 1.f ),
            texture( nullptr )
        {}
 
            //  основной цвет. Зависит от шейдера. 
            //  В стандартных шейдерах будет применяться к текстуре.
            //  Например если текстура белая, то diffuseColor({1.f,0.f,0.f,1.f}) покрасит её в красный.
            //  Вычисление такое. 1 * 1 = 1 красный компонент. 1 * 0 = 0 синий. 1 * 0 = 0 зелёный.
        gtColor diffuseColor;
 
            //  Тип операции смешивания.
        gtMaterialBlendOp   blendOperation;
 
            //  Значение от 1.0 до 0
            //  Работает так: тексель *= level;
        f32     level;
 
        //  текстуры
        gtTexture * texture;
    };
 
    struct gtMaterial{
 
        gtMaterial( void ):
            specularColor( 1.f ),
            specularLevel( 1.f ),
            glossiness( 0.f ),
            opacity( 1.f ),
            fresnel( 1.f ),
            roughness( 0.f ),
            flags( 0u )
        {
        }
 
        ~gtMaterial( void ){}
 
            //  шейдер
        gtShader * shader;
 
            //  цвет затенения. Чёрный по умолчанию.
        gtColor ambientColor;
 
            //  цвет отражённого света
        gtColor specularColor;
 
            //  интенсивность отражения света.
        f32     specularLevel;
            
            //  блеск
        f32     glossiness;
 
            //  шероховатость
        f32     roughness;
 
            //  непрозрачность. Значение от 1 до 0
            //  Для прозрачности должен быть флаг MF_BLEND.
        f32     opacity;
 
            //  пригодится там где нужно
        f32     fresnel; // /fre??n?l/, fray-NEL;
            
            //  флаги
        u32     flags;
 
            //  Тут хранятся указатели на текстуры и параметры для них
        gtMaterialTextureLayer  textureLayer[ 16u ];
    };
 
 
}
 
 
#endif
Опишу класс текстуры
gtTexture.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma once
#ifndef __GT_TEXTURE_H__
#define __GT_TEXTURE_H__
 
/*
    Hardware текстура
*/
 
namespace gost{
 
        //  тип текстуры
    enum gtTextureType : u32 {
 
        //  обычная
        TEXTURE_TYPE_2D,
 
        //  cubemap
        TEXTURE_TYPE_CUBE
    };
 
        //  текстура
    class gtTexture : public gtRefObject {
    public:
 
            //  возвратит тип текстуры
        virtual gtTextureType   getType( void ) = 0;
 
    };
 
 
}
 
 
#endif

Текстура будет создаваться из обычной картинки.
Картинка будет описана в отдельной структуре

gtImage.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#pragma once
#ifndef __GT_IMAGE_H__
#define __GT_IMAGE_H__
 
/*
    Software картинка
*/
 
namespace gost{
 
 
    struct gtImage{
 
        gtImage( void ):
            format( format::FMT_R8G8B8A8 ),
            width( 0u ),
            height( 0u ),
            bits( 32u ),
            mipCount( 1u ),
            data( nullptr ),
            dataSize( 0u ),
            pluginId( -1 )
        {}
 
        ~gtImage( void ){
            if( data ){
                delete []data;
                data = nullptr;
            }
        }
 
 
        enum format{
 
            FMT_R8G8B8A8,
 
            FMT_R8G8B8,
 
 
            //  OpenGL
            FMT_COMPRESSED_RGBA_S3TC_DXT1 = 0x83F1,
            FMT_COMPRESSED_RGBA_S3TC_DXT3 = 0x83F2,
            FMT_COMPRESSED_RGBA_S3TC_DXT5 = 0x83F3
 
        }format;
 
            //  ширина
        u32     width;
 
            //  высота
        u32     height;
 
            //  биты на пиксель
        u32     bits;
 
            //  количество mipMap. 1 - основная картинка
        u32     mipCount;
 
        u8  *   data;
        u32     dataSize;
 
            //  id плагина который загрузил картинку
            //  нужно чтобы потом этот плагин её выгрузил
            //  По умолчанию -1, можно создавать и уничтожать вручную где вздумается
        s32     pluginId;
 
 
    };
 
 
}
 
 
#endif
Пока что достаточно с картинками.

Нужно решить следующую задачу.
Необходимо нарисовать квадрат, без создания hardware буфера.
Этот квадрат будет(но не сегодня) закрашиваться цветом diffuseColor из материала.

Эту задачу должен выполнять
gtDriver
типа так
C++
1
driver->draw2DImage( material );
При рисовании нужно чтобы работал шейдер, значит надо создать ещё кое какие классы/структуры.

я думаю лучше создавать шейдер самому.
не создавать все сразу автоматически, а только те которые нужно.
Возможно в будущем это даст новые возможности, типа, создание шейдеров как в конструкторе, по частям.


gtShader.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#pragma once
#ifndef __GT_SHADER_H__
#define __GT_SHADER_H__
 
/*
*/
 
namespace gost{
 
    struct gtShaderModel{
 
        enum class shaderModel{
            _1_1,       //  OpenGL + DirectX
            _1_2,       //  OpenGL
            _1_3,       //  OpenGL
            _1_4,       //  OpenGL
            _1_5,       //  OpenGL
            _2_0,       //  DirectX
            _3_0,       //  DirectX
            _3_3,       //  OpenGL
            _4_0,       //  OpenGL + DirectX
            _4_1,       //  OpenGL + DirectX
            _4_2,       //  OpenGL
            _4_3,       //  OpenGL
            _4_5,       //  OpenGL
            _5_0,       //  DirectX
            _6_0        //  DirectX
        }vertexShaderModel, pixelShaderModel;
 
    };
 
        //  Шейдер
    class gtShader : public gtRefObject {
    public:
 
        virtual gtShaderModel   getShaderModel( void ) = 0;
 
            //  В d3d11 создаёт константный буффер
        virtual bool    createShaderObject( u32 byteSize ) = 0;
 
    };
 
 
}
 
 
#endif
Начну с функции рисования.
gtDriver
C++
1
2
3
    //  нарисует картинку
    //  rect - координаты левого верхнего и правого нижнего углов
virtual void draw2DImage( const v4f& rect, const gtMaterial& ) = 0;
Реализация в плагине D3D11
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    //  нарисует картинку
    //  rect - координаты левого верхнего и правого нижнего углов
void gtDriverD3D11::draw2DImage( const v4f& rect, const gtMaterial& material ){
    
    gtShader * shader = material.shader;
    if( !shader ){
        shader = m_shader2DStandart;
    }
        
    struct cbVerts{
        v4f v1;
        v4f v2;
        v4f v3;
        v4f v4;
        v2f t1;
        v2f t2;
        v2f t3;
        v2f t4;
    }cb;
 
    //  нужно послать в константный буффер координаты
 
    //  позиция
    cb.v1[ 0 ] = -0.5f; //x     
    cb.v1[ 1 ] = -0.5f; //y     
    cb.v1[ 2 ] = 0.5f;  //z     *
    cb.v1[ 3 ] = 1.f;
 
    cb.v2[ 0 ] = -0.5f; //x     *
    cb.v2[ 1 ] = 0.5f;  //y     |
    cb.v2[ 2 ] = 0.5f;  //z     *
    cb.v2[ 3 ] = 1.f;
 
    cb.v3[ 0 ] = 0.5f;  //x     *-----*
    cb.v3[ 1 ] = 0.5f;  //y     |   /
    cb.v3[ 2 ] = 0.5f;  //z     */
    cb.v3[ 3 ] = 1.f;
 
    cb.v4[ 0 ] = 0.5f;  //x     *-----*
    cb.v4[ 1 ] = -0.5f; //y     |   /
    cb.v4[ 2 ] = 0.5f;  //z     */    *
    cb.v4[ 3 ] = 1.f;
    //индексы указываются в шейдере в ручную с помощью SV_VertexID
 
    setActiveShader( shader );
 
    m_d3d11DevCon->IASetInputLayout( NULL );
    m_d3d11DevCon->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
 
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    m_d3d11DevCon->Map(
        ((gtShaderImpl*)shader)->m_constantBuffers[ 0 ],
        0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );
 
    D3D11_BUFFER_DESC d;
    ((gtShaderImpl*)shader)->m_constantBuffers[ 0 ]->GetDesc( &d );
 
    memcpy( mappedResource.pData, &cb, d.ByteWidth );
    m_d3d11DevCon->Unmap( ((gtShaderImpl*)shader)->m_constantBuffers[ 0 ], 0 );
 
    m_d3d11DevCon->VSSetConstantBuffers( 0, 1, &((gtShaderImpl*)shader)->m_constantBuffers[ 0 ] );
    m_d3d11DevCon->Draw( 6, 0 );
}

Сразу опишу вершину. Пока использоваться не будет.
gtVertex.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#pragma once
#ifndef __GT_VERTEX_H__
#define __GT_VERTEX_H__
 
/*
*/
 
namespace gost{
 
 
 
    /*
        Stride - количество байт на 1 вершину.
 
        минимум
        4 координаты позиции
        3 нормали
        2 текстурных координат
        итого sizeof( gtReal ) * 9u;
    */
 
        //  position + normal + UV
    constexpr u32 gtStrideStandart = sizeof( gtReal ) * 9u;
 
    template< u32 Stride >
    struct gtVertex{
 
        gtVertex( void ){
            GT_STATIC_ASSERT( Stride >= gtStrideStandart, "Stride >= 3u" );
        }
 
        //  размер одной вершины в байтах. Нужно будет убрать в класс с моделью
        //  u32 stride( void ) const { return Stride; }
 
        //  данные
        u8  data[ Stride ];
 
        //  получить данные в удобном для работы виде
        gtReal  *   getFPData( void ){
            return reinterpret_cast<gtReal*>(data);
        }
 
    };
 
    using gtVertexStandart = gtVertex<gtStrideStandart>;
 
    /*
        В структуре с моделью рядом с буфером вершин должно стоять это.
        Он описывает в каком порядке что стоит в вершине.
    */
    enum class gtVertexType{
        position,   //4 * sizeof( gtReal )
        normal,     //3 * sizeof( gtReal )
        uv,         //2 * sizeof( gtReal )
        color,      //4 * sizeof( gtReal )
        binormal,   //3 * sizeof( gtReal )
        tangent,    //3 * sizeof( gtReal )
        end // типа завершающий ноль. должен стоять в конце.
    };
 
 
}
 
 
#endif


Теперь нужно установить используемую шейдерную программу.
Пока для начала шейдер будет в одном файле.
Пусть все шейдеры лежат в отдельной папке.
Рядом с папками include lib bin32 - новая папка shaders
Внутри этой папки создаю текстоввый документ и переименовываю
2d_basic.hlsl

Содержание этого файла(шейдерная программа).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Texture2D tex2d_1;
SamplerState tex2D_sampler_1;
 
cbuffer cbVerts{
    float4 v1;
    float4 v2;
    float4 v3;
    float4 v4;
    float2 t1;
    float2 t2;
    float2 t3;
    float2 t4;
};
 
struct VSIn{
    uint vertexId : SV_VertexID;
};
 
struct VSOut{
    float4 pos : SV_Position;
    float2 uv : TEXCOORD0;
};
 
struct PSOut{
    float4 color : SV_Target;
};
 
VSOut VSMain(VSIn input)
{
    VSOut output;
   
    output.uv = t1;
    
    if( input.vertexId == 0 ){
        output.pos = v1;
    }else if ( input.vertexId == 1 ){
        output.pos = v2;
    }else if ( input.vertexId == 2 ){
        output.pos = v3;
    }else if ( input.vertexId == 3 ){
        output.pos = v1;
    }else if ( input.vertexId == 4 ){
        output.pos = v3;
    }else if ( input.vertexId == 5 ){
        output.pos = v4;
    }
     
    return output;
}
 
 
 
PSOut PSMain(VSOut input)
{
    PSOut output;
    
    //float4 diffuseColor = tex2d_1.Sample(tex2D_sampler_1, input.uv);
    
    output.color.ba = 1.f; // синий и альфа
    output.color.rg = 0.f;  //  красный и зелёный
    
    return output;
}

Нужно создать шейдер - скомпилировать.
gtDriver будет это делать.
добавляю
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
    //  компилировать либо получить ранее скомпилированный шейдер
virtual gtShader *  getShader( 
        //  путь к файлу хранящем вершинный шейдер
    const gtString& vertexShader,
        //  главная функция вершинного шейдера, точка входа
    const gtString& vertexShaderMain,
        //  путь к файлу хранящем пиксельный/фрагментный шейдер
    const gtString& pixelShader,
        //  главная функция пиксельного/фрагментного шейдера, точка входа
    const gtString& pixelShaderMain,
        //  тип шейдерного языка
    gtShaderModel shaderModel
    ) = 0;
реализация (просто компиляция, без получения ранее созданного шейдера)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    //  компилировать либо получить ранее скомпилированный шейдер
gtShader *  gtDriverD3D11::getShader( 
        //  путь к файлу хранящем вершинный шейдер
    const gtString& vertexShader,
        //  главная функция вершинного шейдера, точка входа
    const gtStringA& vertexShaderMain,
        //  путь к файлу хранящем пиксельный/фрагментный шейдер
    const gtString& pixelShader,
        //  главная функция пиксельного/фрагментного шейдера, точка входа
    const gtStringA& pixelShaderMain,
        //  тип шейдерного языка
    gtShaderModel shaderModel,
 
    gtVertexType * vertexType
){
    //  для хранения текста шейдера
    std::unique_ptr<s8[]> vertexBuffer;
    std::unique_ptr<s8[]> pixelBuffer;
 
    //  если указан файл то читаем его
    if( gtFileSystem::existFile( vertexShader ) ){
 
        gtFile_t file = util::openFileForReadText( vertexShader );
 
        u32 sz = file->size();
        
        if( !sz ){
            gtLogWriter::printError( u"Empty shader file [%s]", vertexShader.data() );
            return nullptr;
        }
 
        vertexBuffer.reset( new s8[ sz+1u ] );
        vertexBuffer.get()[sz] = 0;
 
        file->read( (u8*)vertexBuffer.get(), sz );
 
 
    }else{
        //  если указан не файл, то скорее всего текст шейдера.
        u32 sz = vertexShader.size();
        if( !sz ){
            gtLogWriter::printError( u"Empty shader file [%s]", vertexShader.data() );
            return nullptr;
        }
 
        vertexBuffer.reset( new s8[ sz+1u ] );
        vertexBuffer.get()[sz] = 0;
        auto * data = vertexShader.data();
 
        for( u32 i = 0u; i < sz; ++i ){
            auto * b = vertexBuffer.get();
            b[ i ] = (s8)data[ i ];
        }
    }
 
    if( gtFileSystem::existFile( pixelShader ) ){
        gtFile_t file = util::openFileForReadText( pixelShader );
        u32 sz = file->size();
        if( !sz ){
            gtLogWriter::printError( u"Empty shader file [%s]", pixelShader.data() );
            return nullptr;
        }
        pixelBuffer.reset( new s8[ sz+1 ] );
        pixelBuffer.get()[sz] = 0;
 
        file->read( (u8*)pixelBuffer.get(), sz );
    }else{
        u32 sz = pixelShader.size();
        if( !sz ){
            gtLogWriter::printError( u"Empty shader file [%s]", pixelShader.data() );
            return nullptr;
        }
        pixelBuffer.reset( new s8[ sz+1 ] );
        pixelBuffer.get()[sz] = 0;
        auto * data = pixelShader.data();
        for( u32 i = 0u; i < sz; ++i ){
            auto * b = pixelBuffer.get();
            b[ i ] = (s8)data[ i ];
        }
    }
 
    gtStringA v_target;
 
    switch( shaderModel.vertexShaderModel ){
    case gtShaderModel::shaderModel::_1_1:
    case gtShaderModel::shaderModel::_1_2:
    case gtShaderModel::shaderModel::_1_3:
    case gtShaderModel::shaderModel::_1_4:
    case gtShaderModel::shaderModel::_1_5:
        v_target = "vs_1_1";
        break;
    case gtShaderModel::shaderModel::_2_0:
        v_target = "vs_2_0";
        break;
    case gtShaderModel::shaderModel::_3_0:
    case gtShaderModel::shaderModel::_3_3:
        v_target = "vs_3_0";
        break;
    case gtShaderModel::shaderModel::_4_0:
        v_target = "vs_4_0";
        break;
    case gtShaderModel::shaderModel::_4_1:
    case gtShaderModel::shaderModel::_4_2:
    case gtShaderModel::shaderModel::_4_3:
    case gtShaderModel::shaderModel::_4_5:
        v_target = "vs_4_1";
        break;
    case gtShaderModel::shaderModel::_5_0:
        v_target = "vs_5_0";
        break;
    case gtShaderModel::shaderModel::_6_0:
        v_target = "vs_6_0";
        break;
    }
 
    gtStringA p_target;
 
    switch( shaderModel.pixelShaderModel ){
    case gtShaderModel::shaderModel::_1_1:
    case gtShaderModel::shaderModel::_1_2:
    case gtShaderModel::shaderModel::_1_3:
    case gtShaderModel::shaderModel::_1_4:
    case gtShaderModel::shaderModel::_1_5:
        p_target = "ps_1_1";
        break;
    case gtShaderModel::shaderModel::_2_0:
        p_target = "ps_2_0";
        break;
    case gtShaderModel::shaderModel::_3_0:
    case gtShaderModel::shaderModel::_3_3:
        p_target = "ps_3_0";
        break;
    case gtShaderModel::shaderModel::_4_0:
        p_target = "ps_4_0";
        break;
    case gtShaderModel::shaderModel::_4_1:
    case gtShaderModel::shaderModel::_4_2:
    case gtShaderModel::shaderModel::_4_3:
    case gtShaderModel::shaderModel::_4_5:
        p_target = "ps_4_1";
        break;
    case gtShaderModel::shaderModel::_5_0:
        p_target = "ps_5_0";
        break;
    case gtShaderModel::shaderModel::_6_0:
        p_target = "ps_6_0";
        break;
    }
 
    gtPtr< gtShaderImpl > shader = gtPtrNew< gtShaderImpl >( new gtShaderImpl(this) );
 
    if( !shader->compileShader( 
        v_target, 
        p_target,
        vertexBuffer.get(),
        pixelBuffer.get(),
        (s8*)vertexShaderMain.data(),
        (s8*)pixelShaderMain.data(),
        vertexType ) ){
        return nullptr;
    }
 
    shader->addRef();
    return shader.data();
}

Далее нужно реализовать gtShader
В плагине D3D11 создаю новый класс.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#pragma once
#ifndef __GT_SHADER_IMPL_H__
#define __GT_SHADER_IMPL_H__
 
namespace gost{
 
    class gtDriverD3D11;
    class gtShaderImpl GT_FINAL: public gtShader{
 
        gtShaderModel m_shaderModel;
 
        gtDriverD3D11 * m_driver;
    public:
        gtShaderImpl( gtDriverD3D11* );
        virtual ~gtShaderImpl( void );
 
        bool            compileShader(
            const gtStringA& vertexTarget,
            const gtStringA& pixelTarget,
            s8 * vertexShader,
            s8 * pixelShader,
            s8 * vertexEntryPoint,
            s8 * pixelEntryPoint,
            gtVertexType *);
 
        gtShaderModel   getShaderModel( void );
 
            //  В d3d11 создаёт константный буффер
        bool    createShaderObject( u32 byteSize );
        
        ID3D11VertexShader* m_vShader;
        ID3D11PixelShader*  m_pShader;
        ID3D11InputLayout*  m_vLayout;
 
        gtArray<ID3D11Buffer*> m_constantBuffers;
    };
 
}
 
#endif
реализация
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
gtShaderImpl::gtShaderImpl( gtDriverD3D11 * driver ):
    m_vShader( nullptr ),
    m_pShader( nullptr ),
    m_vLayout( nullptr ),
    m_driver( driver )
{}
 
 
gtShaderImpl::~gtShaderImpl( void ){
 
    for each ( auto * var in this->m_constantBuffers ){
        if( var )
            var->Release();
    }
 
    if( m_vLayout )
        m_vLayout->Release();
 
    if( m_vShader )
        m_vShader->Release();
 
    if( m_pShader )
        m_pShader->Release();
 
}
 
bool gtShaderImpl::compileShader(
            const gtStringA& vertexTarget,
            const gtStringA& pixelTarget,
            s8 * vertexShader,
            s8 * pixelShader,
            s8 * vertexEntryPoint,
            s8 * pixelEntryPoint,
            gtVertexType * vertexType ){
 
    gtString compilerPath = gtFileSystem::getSystemPath();
    compilerPath += u"D3dcompiler_43.dll";
 
    if( !gtFileSystem::existFile( compilerPath ) ){
        gtLogWriter::printError( u"D3dcompiler_43.dll not exist" );
        MessageBox( (HWND)m_driver->getParams().m_outWindow->getHandle(),
            L"D3dcompiler_43.dll not exist",
            L"Error", MB_ICONERROR | MB_OK );
        return false;
    }
 
    HMODULE lib = LoadLibrary( (wchar_t*)compilerPath.data() );
    if( !lib ){
        gtLogWriter::printError( u"Can not load D3dcompiler_43.dll. Error code[%u]", GetLastError() );
        MessageBox( (HWND)m_driver->getParams().m_outWindow->getHandle(),
            L"Can not load D3dcompiler_43.dll",
            L"Error", MB_ICONERROR | MB_OK );
        return false;
    }
 
    gtD3DCompile_t  CompileShader = (gtD3DCompile_t)GetProcAddress( lib, "D3DCompile" );
    if( !CompileShader ){
        gtLogWriter::printError( u"Can not get procedure address \"D3DCompile\" from D3dcompiler_43.dll" );
        MessageBox( (HWND)m_driver->getParams().m_outWindow->getHandle(),
            L"Can not get procedure address \"D3DCompile\" from D3dcompiler_43.dll",
            L"Error", MB_ICONERROR | MB_OK );
        FreeLibrary( lib );
        return false;
    }
 
    ID3D10Blob*     m_VsBlob = nullptr;
    ID3D10Blob*     m_PsBlob = nullptr;
    ID3D10Blob*     m_errorBlob = nullptr;
 
    HRESULT hr = CompileShader(
        vertexShader,
        strlen( vertexShader ),
        0, 0, 0,
        vertexEntryPoint,
        vertexTarget.data(),
        0,
        0,
        &m_VsBlob,
        &m_errorBlob
    );
    
    if( FAILED( hr ) ){
        gtString errorMessage;
        s8 * message = (s8*)m_errorBlob->GetBufferPointer();
        u32 len = strlen(message);
        for( u32 i = 0u; i < len; ++i )
            errorMessage += (char16_t)message[ i ];
        gtLogWriter::printError( u"Vertex shader compile error: %s", errorMessage.data() );
        FreeLibrary( lib );
        return false;
    }
 
 
    hr = CompileShader(
        pixelShader,
        strlen( pixelShader ),
        0, 0, 0,
        pixelEntryPoint,
        pixelTarget.data(),
        0,
        0,
        &m_PsBlob,
        &m_errorBlob
    );
    
    
 
    if( FAILED( hr ) ){
        gtString errorMessage;
        s8 * message = (s8*)m_errorBlob->GetBufferPointer();
        u32 len = strlen(message);
        for( u32 i = 0u; i < len; ++i )
            errorMessage += (char16_t)message[ i ];
        gtLogWriter::printError( u"Pixel shader compile error: %s", errorMessage.data() );
        FreeLibrary( lib );
        return false;
    }
 
    auto * d3ddevice = m_driver->getD3DDevice();
 
    hr =  d3ddevice->CreateVertexShader( 
        m_VsBlob->GetBufferPointer(), 
        m_VsBlob->GetBufferSize(),
        0,
        &m_vShader );
    if( FAILED( hr ) ){
        gtLogWriter::printError( u"Can't create vertex shader. Error code [%u]", hr );
        FreeLibrary( lib );
        return false;
    }
 
    hr =  d3ddevice->CreatePixelShader( 
        m_PsBlob->GetBufferPointer(), 
        m_PsBlob->GetBufferSize(),
        0,
        &m_pShader );
    if( FAILED( hr ) ){
        gtLogWriter::printError( u"Can't create pixel shader. Error code [%u]", hr );
        FreeLibrary( lib );
        return false;
    }
 
    u32 vertexLayoutComponentSize = 0u;
 
    for( u32 i = 0u; i < 1024u; ++i ){
        if( vertexType[ i ] == gtVertexType::end )
            break;
        else
            vertexLayoutComponentSize++;
 
        if( i == 100u ){
            gtLogWriter::printError( u"Can't create shader. Bad vertex type" );
            FreeLibrary( lib );
            return false;
        }
    }
 
    //  пока нет возможности это протестировать
    std::unique_ptr< D3D11_INPUT_ELEMENT_DESC[] > layout( new D3D11_INPUT_ELEMENT_DESC[ vertexLayoutComponentSize ] );
 
    UINT offset = 0u;
 
    for( u32 i = 0u; i < vertexLayoutComponentSize; ++i ){
        if( vertexType[ i ] == gtVertexType::position ){
 
            layout.get()[ i ] = { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offset,  D3D11_INPUT_PER_VERTEX_DATA, 0 };
            offset += 12;
 
        }else if( vertexType[ i ] == gtVertexType::uv ){
 
            layout.get()[ i ] = { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,    0, offset, D3D11_INPUT_PER_VERTEX_DATA, 0 };
            offset += 8;
 
        }else if( vertexType[ i ] == gtVertexType::normal ){
 
            layout.get()[ i ] = { "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offset, D3D11_INPUT_PER_VERTEX_DATA, 0 };
            offset += 12;
 
        }else if( vertexType[ i ] == gtVertexType::binormal ){
 
            layout.get()[ i ] = { "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offset, D3D11_INPUT_PER_VERTEX_DATA, 0 };
            offset += 12;
 
        }else if( vertexType[ i ] == gtVertexType::tangent ){
 
            layout.get()[ i ] = { "TANGENT",  0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offset, D3D11_INPUT_PER_VERTEX_DATA, 0 };
            offset += 12;
 
        }else if( vertexType[ i ] == gtVertexType::color ){
 
            layout.get()[ i ] = { "COLOR",     0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offset, D3D11_INPUT_PER_VERTEX_DATA, 0 };
            offset += 16;
 
        }
    }
 
    hr = d3ddevice->CreateInputLayout(
        layout.get(),
        vertexLayoutComponentSize,
        m_VsBlob->GetBufferPointer(),
        m_VsBlob->GetBufferSize(),
        &m_vLayout );
    if( FAILED( hr ) ){
        gtLogWriter::printError( u"Can't create input layout. Error code [%u]", hr );
        FreeLibrary( lib );
        return false;
    }
 
    if( m_VsBlob )
        m_VsBlob->Release();
        m_VsBlob = nullptr;
 
    if( m_PsBlob )
        m_PsBlob->Release();
        m_PsBlob = nullptr;
 
    if( m_errorBlob )
        m_errorBlob->Release();
        m_errorBlob = nullptr;
 
    FreeLibrary( lib );
    return true;
}
 
gtShaderModel   gtShaderImpl::getShaderModel( void ){
    return m_shaderModel;
}
 
bool gtShaderImpl::createShaderObject( u32 byteSize ){
    D3D11_BUFFER_DESC mbd { 0 };
    mbd.Usage   =   D3D11_USAGE_DYNAMIC;
    mbd.ByteWidth   =   byteSize;
    mbd.BindFlags   =   D3D11_BIND_CONSTANT_BUFFER;
    mbd.CPUAccessFlags  =   D3D11_CPU_ACCESS_WRITE;
    mbd.MiscFlags   =   0;
    mbd.StructureByteStride =   0;
 
    ID3D11Buffer* buffer = nullptr;
 
    HRESULT hr  =   m_driver->getD3DDevice()->CreateBuffer( &mbd, 0, &buffer );
    if( FAILED( hr ) ){
        gtLogWriter::printError( u"Can't create constant buffer. Error code [%u]", hr );
        return false;
    }
 
    this->m_constantBuffers.push_back( buffer );
 
    return true;
}



Добавил в gtDriverD3D11
C++
1
2
3
4
5
6
7
8
9
10
HMODULE gtDriverD3D11::getD3DLibraryHandle( void ){
    return m_D3DLibrary;
}
ID3D11Device * gtDriverD3D11::getD3DDevice( void ){
    return m_d3d11Device;
}
void gtDriverD3D11::setActiveShader( gtShader* shader ){
    m_d3d11DevCon->VSSetShader( ((gtShaderImpl*)shader)->m_vShader, 0, 0 );
    m_d3d11DevCon->PSSetShader( ((gtShaderImpl*)shader)->m_pShader, 0, 0 );
}
В gtDriverD3D11::initialize
в конце
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//  в будущем стандартные шейдеры нужно убрать внутрь плагина
    gtShaderModel shaderModel;
    shaderModel.pixelShaderModel = gtShaderModel::shaderModel::_5_0;
    shaderModel.vertexShaderModel = gtShaderModel::shaderModel::_5_0;
 
    gtVertexType vertexType[] = 
    {
        { gtVertexType::position },
        { gtVertexType::end }
    };
 
    m_shader2DStandart = getShader( 
        u"../shaders/2d_basic.hlsl",
        "VSMain",
        u"../shaders/2d_basic.hlsl",
        "PSMain",
        shaderModel,
        vertexType
        );
    if( m_shader2DStandart ){
 
        //  создание константного буффера.
        if( !m_shader2DStandart->createShaderObject( 96u ) ) return false;
    }

для автоматического освобождения памяти сделал тип gtPtr
C++
1
2
//  загруженные плагины
gtList<gtPtr<gtPluginRender>>   m_renderPlugins;
деструктор пустой
C++
1
gtPluginSystemImpl::~gtPluginSystemImpl( void ){}
и подправил
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
gtDriver*   gtPluginSystemImpl::loadRenderPlugin( const gtDriverInfo& params ){
    
    u32 sz = m_renderPluginCache.size();
 
    if( !sz ){
        gtLogWriter::printError( u"Can not load render plugin [%s]. No plugin.", params.m_GUID.data() );
        return nullptr;
    }
 
    for( u32 i = 0u; i < sz; ++i ){
        auto * o = &m_renderPluginCache[ i ];
        if( o->m_info.m_GUID == params.m_GUID ){
 
            gtPtr<gtPluginRender> render = gtPtrNew<gtPluginRender>( new gtPluginRender( o ) );
            render->load( params );
            
            m_renderPlugins.add( render.data() );
 
            // gtDriver* m_driver;
            return render->m_driver;
        }
    }
    
    
    return nullptr;
}

программа
C++
1
2
3
4
5
6
7
8
9
10
11
gtMaterial material;
 
    while( my_system->update() ){
 
        if( driver1 ){
            driver1->beginRender(true,gtColor(1.f,0.f,0.f,1.f));
            driver1->draw2DImage(v4f({1,1,1,1}),material);
            driver1->endRender();
    }
 
}



Текущая версия https://github.com/532235/GoST/tree/532235-patch-4
Последняя версия https://github.com/532235/GoST
Миниатюры
Нажмите на изображение для увеличения
Название: 412.JPG
Просмотров: 156
Размер:	25.3 Кб
ID:	4551  
Размещено в Игровой движок
Просмотров 282 Комментарии 2
Всего комментариев 2

Комментарии

  1. Старый комментарий
    Ну, неужели не понятно, что качество изложения не определяется размером шрифта, а тем более содержание.
    Запись от ovva размещена 15.12.2017 в 17:51 ovva вне форума
  2. Старый комментарий
    Аватар для 532235
    Цитата:
    Сообщение от ovva Просмотреть комментарий
    Ну, неужели не понятно, что качество изложения не определяется размером шрифта, а тем более содержание.
    непонял.

    цвет и размер только для общего вида(если есть эти функции почему бы не воспользоваться).

    незнаю что и добавить по этому поводу.

    удачи, счастья и любви.
    Запись от 532235 размещена 15.12.2017 в 18:06 532235 вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.