-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
ShaderUniforms.h
140 lines (127 loc) · 4.28 KB
/
ShaderUniforms.h
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
#pragma once
#include <cstdint>
#include "ShaderCommon.h"
// Used by the "modern" backends that use uniform buffers. They can share this without issue.
enum : uint64_t {
DIRTY_BASE_UNIFORMS =
DIRTY_WORLDMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_VIEWMATRIX | DIRTY_TEXMATRIX | DIRTY_ALPHACOLORREF |
DIRTY_PROJMATRIX | DIRTY_FOGCOLOR | DIRTY_FOGCOEF | DIRTY_TEXENV | DIRTY_STENCILREPLACEVALUE |
DIRTY_ALPHACOLORMASK | DIRTY_SHADERBLEND | DIRTY_COLORWRITEMASK | DIRTY_UVSCALEOFFSET | DIRTY_TEXCLAMP | DIRTY_DEPTHRANGE | DIRTY_MATAMBIENTALPHA |
DIRTY_BEZIERSPLINE | DIRTY_DEPAL,
DIRTY_LIGHT_UNIFORMS =
DIRTY_LIGHT_CONTROL | DIRTY_LIGHT0 | DIRTY_LIGHT1 | DIRTY_LIGHT2 | DIRTY_LIGHT3 |
DIRTY_MATDIFFUSE | DIRTY_MATSPECULAR | DIRTY_MATEMISSIVE | DIRTY_AMBIENT,
};
// Currently 448 bytes.
// Every line here is a 4-float.
struct alignas(16) UB_VS_FS_Base {
float proj[16];
float proj_through[16];
float view[12];
float world[12];
float tex[12];
float uvScaleOffset[4];
float depthRange[4];
// Rotation is used only for software transform.
float matAmbient[4];
float cullRangeMin[4];
float cullRangeMax[4];
uint32_t spline_counts; uint32_t depal_mask_shift_off_fmt; // 4 params packed into one.
uint32_t colorWriteMask; float mipBias;
// Fragment data
float fogColor[3]; uint32_t alphaColorRef;
float texEnvColor[3]; uint32_t colorTestMask;
float blendFixA[3]; float stencil;
float blendFixB[3]; float rotation;
float texClamp[4];
float texClampOffset[2]; float fogCoef[2];
// VR stuff is to go here, later. For normal drawing, we can then get away
// with just uploading the first 448 bytes of the struct (up to and including fogCoef).
};
static const char * const ub_baseStr =
R"( mat4 u_proj;
mat4 u_proj_through;
mat3x4 u_view;
mat3x4 u_world;
mat3x4 u_texmtx;
vec4 u_uvscaleoffset;
vec4 u_depthRange;
vec4 u_matambientalpha;
vec4 u_cullRangeMin;
vec4 u_cullRangeMax;
uint u_spline_counts;
uint u_depal_mask_shift_off_fmt;
uint u_colorWriteMask;
float u_mipBias;
vec3 u_fogcolor; uint u_alphacolorref;
vec3 u_texenv; uint u_alphacolormask;
vec3 u_blendFixA; float u_stencilReplaceValue;
vec3 u_blendFixB; float u_rotation;
vec4 u_texclamp;
vec2 u_texclampoff;
vec2 u_fogcoef;
)";
// 512 bytes. Would like to shrink more. Some colors only have 8-bit precision and we expand
// them to float unnecessarily, could just as well expand in the shader.
struct alignas(16) UB_VS_Lights {
float ambientColor[4];
float materialDiffuse[4];
float materialSpecular[4];
float materialEmissive[3];
uint32_t lightControl;
float lpos[4][4];
float ldir[4][4];
float latt[4][4];
float lightAngle_SpotCoef[4][4]; // TODO: Merge with lightSpotCoef, use .xy
float lightAmbient[4][4];
float lightDiffuse[4][4];
float lightSpecular[4][4];
};
static const char * const ub_vs_lightsStr =
R"( vec4 u_ambient;
vec3 u_matdiffuse;
vec4 u_matspecular;
vec3 u_matemissive;
uint u_lightControl; // light ubershader
vec3 u_lightpos0;
vec3 u_lightpos1;
vec3 u_lightpos2;
vec3 u_lightpos3;
vec3 u_lightdir0;
vec3 u_lightdir1;
vec3 u_lightdir2;
vec3 u_lightdir3;
vec3 u_lightatt0;
vec3 u_lightatt1;
vec3 u_lightatt2;
vec3 u_lightatt3;
vec4 u_lightangle_spotCoef0;
vec4 u_lightangle_spotCoef1;
vec4 u_lightangle_spotCoef2;
vec4 u_lightangle_spotCoef3;
vec3 u_lightambient0;
vec3 u_lightambient1;
vec3 u_lightambient2;
vec3 u_lightambient3;
vec3 u_lightdiffuse0;
vec3 u_lightdiffuse1;
vec3 u_lightdiffuse2;
vec3 u_lightdiffuse3;
vec3 u_lightspecular0;
vec3 u_lightspecular1;
vec3 u_lightspecular2;
vec3 u_lightspecular3;
)";
// With some cleverness, we could get away with uploading just half this when only the four or five first
// bones are being used. This is 384b.
struct alignas(16) UB_VS_Bones {
float bones[8][12];
};
static const char * const ub_vs_bonesStr =
R"( mat3x4 u_bone0; mat3x4 u_bone1; mat3x4 u_bone2; mat3x4 u_bone3; mat3x4 u_bone4; mat3x4 u_bone5; mat3x4 u_bone6; mat3x4 u_bone7; mat3x4 u_bone8;
)";
void CalcCullRange(float minValues[4], float maxValues[4], bool flipViewport, bool hasNegZ);
void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipViewport, bool useBufferedRendering);
void LightUpdateUniforms(UB_VS_Lights *ub, uint64_t dirtyUniforms);
void BoneUpdateUniforms(UB_VS_Bones *ub, uint64_t dirtyUniforms);
uint32_t PackLightControlBits();