0027919: Visualization - support multiple transformation persistence groups within...
[occt.git] / src / Graphic3d / Graphic3d_ShaderObject.cxx
CommitLineData
30f0ad28 1// Created on: 2013-09-20
2// Created by: Denis BOGOLEPOV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
30f0ad28 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
30f0ad28 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
30f0ad28 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
30f0ad28 15
4bf072e4 16#include <Graphic3d_ShaderObject.hxx>
17
18#include <Graphic3d_GraphicDriver.hxx>
30f0ad28 19#include <OSD_File.hxx>
20#include <OSD_Protection.hxx>
21#include <Standard_Atomic.hxx>
30f0ad28 22
92efcf78 23IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ShaderObject,Standard_Transient)
24
30f0ad28 25namespace
26{
27 static volatile Standard_Integer THE_SHADER_OBJECT_COUNTER = 0;
a3f6f591 28}
30f0ad28 29
30f0ad28 30// =======================================================================
31// function : Graphic3d_ShaderObject
32// purpose : Creates a shader object from specified file
33// =======================================================================
34Graphic3d_ShaderObject::Graphic3d_ShaderObject (const Graphic3d_TypeOfShaderObject theType)
35: myType (theType)
36{
37 myID = TCollection_AsciiString ("Graphic3d_ShaderObject_")
38 + TCollection_AsciiString (Standard_Atomic_Increment (&THE_SHADER_OBJECT_COUNTER));
39}
40
41// =======================================================================
42// function : CreatFromFile
43// purpose : Creates new shader object from specified file
44// =======================================================================
45Handle(Graphic3d_ShaderObject) Graphic3d_ShaderObject::CreateFromFile (const Graphic3d_TypeOfShaderObject theType,
46 const TCollection_AsciiString& thePath)
47{
48 Handle(Graphic3d_ShaderObject) aShader = new Graphic3d_ShaderObject (theType);
49 aShader->myPath = thePath;
50
51 OSD_File aFile (thePath);
52 if (!aFile.Exists())
53 {
54 return NULL;
55 }
56
57 aFile.Open (OSD_ReadOnly, OSD_Protection());
bd0b3e60 58 aFile.Read (aShader->mySource, (int)aFile.Size());
30f0ad28 59 aFile.Close();
60
61 return aShader;
62}
63
64// =======================================================================
65// function : CreatFromSource
66// purpose : Creates new shader object from specified source
67// =======================================================================
68Handle(Graphic3d_ShaderObject) Graphic3d_ShaderObject::CreateFromSource (const Graphic3d_TypeOfShaderObject theType,
69 const TCollection_AsciiString& theSource)
70{
71 Handle(Graphic3d_ShaderObject) aShader = new Graphic3d_ShaderObject (theType);
72 aShader->mySource = theSource;
73 return aShader;
74}
75
76// =======================================================================
77// function : ~Graphic3d_ShaderObject
78// purpose : Releases resources of shader object
79// =======================================================================
80Graphic3d_ShaderObject::~Graphic3d_ShaderObject()
81{
82 //
83}
84
85// =======================================================================
86// function : IsDone
87// purpose : Checks if the shader object is valid or not
88// =======================================================================
89Standard_Boolean Graphic3d_ShaderObject::IsDone() const
90{
91 return !mySource.IsEmpty();
92}
4bf072e4 93
94// =======================================================================
95// function : CreateFromSource
96// purpose :
97// =======================================================================
98Handle(Graphic3d_ShaderObject) Graphic3d_ShaderObject::CreateFromSource (TCollection_AsciiString& theSource,
99 Graphic3d_TypeOfShaderObject theType,
100 const ShaderVariableList& theUniforms,
101 const ShaderVariableList& theStageInOuts,
102 const TCollection_AsciiString& theInName,
103 const TCollection_AsciiString& theOutName,
104 Standard_Integer theNbGeomInputVerts)
105{
106 if (theSource.IsEmpty())
107 {
108 return Handle(Graphic3d_ShaderObject)();
109 }
110
111 TCollection_AsciiString aSrcUniforms, aSrcInOuts, aSrcInStructs, aSrcOutStructs;
112 for (ShaderVariableList::Iterator anUniformIter (theUniforms); anUniformIter.More(); anUniformIter.Next())
113 {
114 const ShaderVariable& aVar = anUniformIter.Value();
115 if ((aVar.Stages & theType) != 0)
116 {
117 aSrcUniforms += TCollection_AsciiString("\nuniform ") + aVar.Name + ";";
118 }
119 }
120 for (ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next())
121 {
122 const ShaderVariable& aVar = aVarListIter.Value();
123 Standard_Integer aStageLower = IntegerLast(), aStageUpper = IntegerFirst();
124 Standard_Integer aNbStages = 0;
125 for (Standard_Integer aStageIter = Graphic3d_TOS_VERTEX; aStageIter <= (Standard_Integer )Graphic3d_TOS_COMPUTE; aStageIter = aStageIter << 1)
126 {
127 if ((aVar.Stages & aStageIter) != 0)
128 {
129 ++aNbStages;
130 aStageLower = Min (aStageLower, aStageIter);
131 aStageUpper = Max (aStageUpper, aStageIter);
132 }
133 }
134 if ((Standard_Integer )theType < aStageLower
135 || (Standard_Integer )theType > aStageUpper)
136 {
137 continue;
138 }
139
140 const Standard_Boolean hasGeomStage = theNbGeomInputVerts > 0
141 && aStageLower < Graphic3d_TOS_GEOMETRY
142 && aStageUpper >= Graphic3d_TOS_GEOMETRY;
143 const Standard_Boolean isAllStagesVar = aStageLower == Graphic3d_TOS_VERTEX
144 && aStageUpper == Graphic3d_TOS_FRAGMENT;
145 if (hasGeomStage
146 || !theInName.IsEmpty()
147 || !theOutName.IsEmpty())
148 {
149 if (aSrcInStructs.IsEmpty()
150 && aSrcOutStructs.IsEmpty()
151 && isAllStagesVar)
152 {
153 if (theType == aStageLower)
154 {
155 aSrcOutStructs = "\nout VertexData\n{";
156 }
157 else if (theType == aStageUpper)
158 {
159 aSrcInStructs = "\nin VertexData\n{";
160 }
161 else // requires theInName/theOutName
162 {
163 aSrcInStructs = "\nin VertexData\n{";
164 aSrcOutStructs = "\nout VertexData\n{";
165 }
166 }
167 }
168
169 if (isAllStagesVar
170 && (!aSrcInStructs.IsEmpty()
171 || !aSrcOutStructs.IsEmpty()))
172 {
173 if (!aSrcInStructs.IsEmpty())
174 {
175 aSrcInStructs += TCollection_AsciiString("\n ") + aVar.Name + ";";
176 }
177 if (!aSrcOutStructs.IsEmpty())
178 {
179 aSrcOutStructs += TCollection_AsciiString("\n ") + aVar.Name + ";";
180 }
181 }
182 else
183 {
184 if (theType == aStageLower)
185 {
186 aSrcInOuts += TCollection_AsciiString("\nTHE_SHADER_OUT ") + aVar.Name + ";";
187 }
188 else if (theType == aStageUpper)
189 {
190 aSrcInOuts += TCollection_AsciiString("\nTHE_SHADER_IN ") + aVar.Name + ";";
191 }
192 }
193 }
194
195 if (theType == Graphic3d_TOS_GEOMETRY)
196 {
197 aSrcUniforms.Prepend (TCollection_AsciiString()
198 + "\nlayout (triangles) in;"
199 "\nlayout (triangle_strip, max_vertices = " + theNbGeomInputVerts + ") out;");
200 }
201 if (!aSrcInStructs.IsEmpty()
202 && theType == Graphic3d_TOS_GEOMETRY)
203 {
204 aSrcInStructs += TCollection_AsciiString ("\n} ") + theInName + "[" + theNbGeomInputVerts + "];";
205 }
206 else if (!aSrcInStructs.IsEmpty())
207 {
208 aSrcInStructs += "\n}";
209 if (!theInName.IsEmpty())
210 {
211 aSrcInStructs += " ";
212 aSrcInStructs += theInName;
213 }
214 aSrcInStructs += ";";
215 }
216 if (!aSrcOutStructs.IsEmpty())
217 {
218 aSrcOutStructs += "\n}";
219 if (!theOutName.IsEmpty())
220 {
221 aSrcOutStructs += " ";
222 aSrcOutStructs += theOutName;
223 }
224 aSrcOutStructs += ";";
225 }
226
227 theSource.Prepend (aSrcUniforms + aSrcInStructs + aSrcOutStructs + aSrcInOuts);
228 return Graphic3d_ShaderObject::CreateFromSource (theType, theSource);
229}