44
44
#include " IECoreGL/Exception.h"
45
45
#include " IECoreGL/TypedStateComponent.h"
46
46
#include " IECoreGL/ShaderStateComponent.h"
47
+ #include " IECoreGL/ShaderLoader.h"
47
48
#include " IECoreGL/Shader.h"
48
49
#include " IECoreGL/NumericTraits.h"
49
50
#include " IECoreGL/UniformFunctions.h"
@@ -74,66 +75,60 @@ IECOREGL_TYPEDSTATECOMPONENT_SPECIALISEANDINSTANTIATE( Primitive::PointWidth, Pr
74
75
IECOREGL_TYPEDSTATECOMPONENT_SPECIALISEANDINSTANTIATE ( Primitive::Selectable, PrimitiveSelectableTypeId, bool , true );
75
76
IECOREGL_TYPEDSTATECOMPONENT_SPECIALISEANDINSTANTIATE ( Primitive::TransparencySort, PrimitiveTransparencySortStateComponentTypeId, bool , true );
76
77
77
- }
78
+ } // namespace IECoreGL
78
79
79
80
// ////////////////////////////////////////////////////////////////////////
80
- // Primitive implementation
81
+ // Utilities
81
82
// ////////////////////////////////////////////////////////////////////////
82
83
83
- IE_CORE_DEFINERUNTIMETYPED ( Primitive );
84
-
85
- Primitive::Primitive ()
84
+ namespace
86
85
{
87
- }
88
86
89
- Primitive::~Primitive ()
87
+ struct FlatConstant
90
88
{
91
- }
92
89
93
- void Primitive::addPrimitiveVariable ( const std::string &name, const IECore::PrimitiveVariable &primVar )
94
- {
95
- if ( primVar.interpolation == IECore::PrimitiveVariable::Constant )
90
+ FlatConstant ( const IECore::MurmurHash &hash, const Shader::ConstSetupPtr &shaderSetup = Shader::ConstSetupPtr() )
91
+ : hash( hash ), shaderSetup( shaderSetup )
96
92
{
97
- addUniformAttribute ( name, primVar.data );
98
93
}
99
- else
94
+
95
+ IECore::MurmurHash hash;
96
+ Shader::ConstSetupPtr shaderSetup;
97
+
98
+ bool operator < ( const FlatConstant &rhs )
100
99
{
101
- addVertexAttribute ( name, primVar. data ) ;
100
+ return hash < rhs. hash ;
102
101
}
103
- }
104
102
105
- static Shader *constant2 ()
103
+ };
104
+
105
+ // Makes a constant shader by taking the vertex and geometry
106
+ // shader from the state and combining them with a flat fragment
107
+ // shader.
108
+ const Shader::Setup *flatConstantShaderSetup ( State *state, bool forIDRender )
106
109
{
110
+ ShaderStateComponent *shaderStateComponent = state->get <ShaderStateComponent>();
107
111
108
- static const char *vertexSource =
109
-
110
- " #if __VERSION__ <= 120\n "
111
- " #define in attribute\n "
112
- " #define out varying\n "
113
- " #endif\n "
114
- " "
115
- " in vec3 vertexP;"
116
- " "
117
- " void main()"
118
- " {"
119
- " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4( vertexP, 1 );"
120
- " }" ;
121
-
122
- static const char *fragmentSource =
123
-
124
- " void main()"
125
- " {"
126
- " gl_FragColor = vec4( 1, 1, 1, 1 );"
127
- " }" ;
112
+ // Get a hash to represent the shader we're about to make.
113
+ IECore::MurmurHash hash = shaderStateComponent->hash ();
114
+ hash.append ( forIDRender );
128
115
129
- static ShaderPtr s = new Shader ( vertexSource, fragmentSource );
130
- return s.get ();
131
- }
116
+ // If we've made an equivalent shader before, then
117
+ // just return it.
118
+ static vector<FlatConstant> flatConstants;
119
+ vector<FlatConstant>::iterator it = lower_bound (
120
+ flatConstants.begin (),
121
+ flatConstants.end (),
122
+ hash
123
+ );
124
+ if ( it != flatConstants.end () && it->hash == hash )
125
+ {
126
+ return it->shaderSetup .get ();
127
+ }
132
128
133
- static Shader *flatConstant ()
134
- {
129
+ // If we haven't, then make one.
135
130
136
- static const char *fragmentSource =
131
+ static const std::string constantFragmentSource =
137
132
138
133
" uniform vec3 Cs;" // get colour from uniform Cs, bypassing vertexCs
139
134
" "
@@ -142,10 +137,48 @@ static Shader *flatConstant()
142
137
" gl_FragColor = vec4( Cs, 1 );"
143
138
" }" ;
144
139
145
- static ShaderPtr s = new Shader ( " " , fragmentSource );
146
- return s.get ();
140
+ const std::string &fragmentSource = forIDRender ? Selector::defaultIDShader ()->fragmentSource () : constantFragmentSource;
141
+
142
+ const Shader *originalShader = shaderStateComponent->shaderSetup ()->shader ();
143
+ ShaderLoader *shaderLoader = shaderStateComponent->shaderLoader ();
144
+ ConstShaderPtr shader = shaderLoader->create ( originalShader->vertexSource (), originalShader->geometrySource (), fragmentSource );
145
+ Shader::SetupPtr shaderSetup = new Shader::Setup ( shader );
146
+ shaderStateComponent->addParametersToShaderSetup ( shaderSetup.get () );
147
+
148
+ // Put it in our store so we don't have to remake it next time.
149
+
150
+ flatConstants.insert ( it, FlatConstant ( hash, shaderSetup.get () ) );
151
+
152
+ return shaderSetup.get ();
147
153
}
148
154
155
+ } // namespace
156
+
157
+ // ////////////////////////////////////////////////////////////////////////
158
+ // Primitive implementation
159
+ // ////////////////////////////////////////////////////////////////////////
160
+
161
+ IE_CORE_DEFINERUNTIMETYPED ( Primitive );
162
+
163
+ Primitive::Primitive ()
164
+ {
165
+ }
166
+
167
+ Primitive::~Primitive ()
168
+ {
169
+ }
170
+
171
+ void Primitive::addPrimitiveVariable ( const std::string &name, const IECore::PrimitiveVariable &primVar )
172
+ {
173
+ if ( primVar.interpolation == IECore::PrimitiveVariable::Constant )
174
+ {
175
+ addUniformAttribute ( name, primVar.data );
176
+ }
177
+ else
178
+ {
179
+ addVertexAttribute ( name, primVar.data );
180
+ }
181
+ }
149
182
150
183
void Primitive::render ( State *state ) const
151
184
{
@@ -163,9 +196,10 @@ void Primitive::render( State *state ) const
163
196
// with a simple shader and early out.
164
197
if ( currentSelector && currentSelector->mode () == Selector::GLSelect )
165
198
{
166
- const Shader *constantShader = constant2 ();
167
- const Shader::Setup *constantSetup = shaderSetup ( constantShader, state );
168
- Shader::Setup::ScopedBinding constantBinding ( *constantSetup );
199
+ const Shader::Setup *uniformSetup = flatConstantShaderSetup ( state, /* forIDRender = */ false );
200
+ Shader::Setup::ScopedBinding uniformBinding ( *uniformSetup );
201
+ const Shader::Setup *primitiveSetup = shaderSetup ( uniformSetup->shader (), state );
202
+ Shader::Setup::ScopedBinding primitiveBinding ( *primitiveSetup );
169
203
render ( state, Primitive::DrawSolid::staticTypeId () );
170
204
return ;
171
205
}
@@ -177,8 +211,18 @@ void Primitive::render( State *state ) const
177
211
{
178
212
glDepthMask ( !depthSortRequested ( state ) );
179
213
// the state itself will have a shader with some nice uniform parameter
180
- // values. we are responsible for binding this setup.
181
- Shader::Setup *uniformSetup = state->get <ShaderStateComponent>()->shaderSetup ();
214
+ // values. we are responsible for binding this setup. unless we're performing
215
+ // an id render for selection, in which case we're responsible for binding an
216
+ // id shader.
217
+ const Shader::Setup *uniformSetup = NULL ;
218
+ if ( currentSelector && currentSelector->mode () == Selector::IDRender )
219
+ {
220
+ uniformSetup = flatConstantShaderSetup ( state, /* forIDRender = */ true );
221
+ }
222
+ else
223
+ {
224
+ uniformSetup = state->get <ShaderStateComponent>()->shaderSetup ();
225
+ }
182
226
Shader::Setup::ScopedBinding uniformBinding ( *uniformSetup );
183
227
// we then bind our own setup on top, adding in the parameters
184
228
// stored on the primitive itself.
@@ -210,18 +254,18 @@ void Primitive::render( State *state ) const
210
254
}
211
255
212
256
// get a constant shader suitable for drawing wireframes, points etc.
213
- const Shader *constantShader = flatConstant ();
214
- if ( currentSelector && currentSelector-> mode () == Selector::IDRender )
215
- {
216
- // if we're in IDRender mode, then the constant shader is unsuitable,
217
- // and we should instead use the ID shader we've been given.
218
- constantShader = state-> get <ShaderStateComponent>()-> shaderSetup ()-> shader ( );
219
- }
220
-
221
- const Shader::Setup *constantSetup = shaderSetup ( constantShader, state );
222
- Shader::Setup::ScopedBinding constantBinding ( *constantSetup );
257
+ // we do this by taking the current shader from the state and overriding
258
+ // just the fragment shader within it - we want to keep any vertex or
259
+ // geometry shader the user has specified. again, if we're performing an
260
+ // id render, we're responsible for binding an id shader instead.
261
+ const Shader::Setup *uniformSetup = flatConstantShaderSetup ( state, currentSelector && currentSelector-> mode () == Selector::IDRender );
262
+ Shader::Setup::ScopedBinding uniformBinding ( *uniformSetup );
263
+
264
+ const Shader::Setup *primitiveSetup = shaderSetup ( uniformSetup-> shader (), state );
265
+ Shader::Setup::ScopedBinding primitiveBinding ( *primitiveSetup );
266
+
223
267
GLint csIndex = -1 ;
224
- if ( const Shader::Parameter *csParameter = constantSetup ->shader ()->csParameter () )
268
+ if ( const Shader::Parameter *csParameter = uniformSetup ->shader ()->csParameter () )
225
269
{
226
270
csIndex = csParameter->location ;
227
271
}
0 commit comments