1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2018 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26
27 #include "ShaderWrapper.h"
28
29 #include <Core/Geometry/Geometry.h>
30 #include <Core/Utility/Console.h>
31
32 namespace three{
33
34 namespace glsl {
35
Render(const Geometry & geometry,const RenderOption & option,const ViewControl & view)36 bool ShaderWrapper::Render(const Geometry &geometry, const RenderOption &option,
37 const ViewControl &view)
38 {
39 if (compiled_ == false) {
40 Compile();
41 }
42 if (bound_ == false) {
43 BindGeometry(geometry, option, view);
44 }
45 if (compiled_ == false || bound_ == false) {
46 PrintShaderWarning("Something is wrong in compiling or binding.");
47 return false;
48 }
49 return RenderGeometry(geometry, option, view);
50 }
51
InvalidateGeometry()52 void ShaderWrapper::InvalidateGeometry()
53 {
54 if (bound_) {
55 UnbindGeometry();
56 }
57 }
58
PrintShaderWarning(const std::string & message) const59 void ShaderWrapper::PrintShaderWarning(const std::string &message) const
60 {
61 PrintWarning("[%s] %s\n", GetShaderName().c_str(), message.c_str());
62 }
63
CompileShaders(const char * const vertex_shader_code,const char * const geometry_shader_code,const char * const fragment_shader_code)64 bool ShaderWrapper::CompileShaders(
65 const char * const vertex_shader_code,
66 const char * const geometry_shader_code,
67 const char * const fragment_shader_code)
68 {
69 if (compiled_) {
70 return true;
71 }
72
73 if (vertex_shader_code != NULL) {
74 vertex_shader_ = glCreateShader(GL_VERTEX_SHADER);
75 const GLchar *vertex_shader_code_buffer = vertex_shader_code;
76 glShaderSource(vertex_shader_, 1, &vertex_shader_code_buffer, NULL);
77 glCompileShader(vertex_shader_);
78 if (ValidateShader(vertex_shader_) == false) {
79 return false;
80 }
81 }
82
83 if (geometry_shader_code != NULL) {
84 geometry_shader_ = glCreateShader(GL_GEOMETRY_SHADER);
85 const GLchar *geometry_shader_code_buffer = geometry_shader_code;
86 glShaderSource(geometry_shader_, 1, &geometry_shader_code_buffer, NULL);
87 glCompileShader(geometry_shader_);
88 if (ValidateShader(geometry_shader_) == false) {
89 return false;
90 }
91 }
92
93 if (fragment_shader_code != NULL) {
94 fragment_shader_ = glCreateShader(GL_FRAGMENT_SHADER);
95 const GLchar *fragment_shader_code_buffer = fragment_shader_code;
96 glShaderSource(fragment_shader_, 1, &fragment_shader_code_buffer, NULL);
97 glCompileShader(fragment_shader_);
98 if (ValidateShader(fragment_shader_) == false) {
99 return false;
100 }
101 }
102
103 program_ = glCreateProgram();
104 if (vertex_shader_code != NULL) {
105 glAttachShader(program_, vertex_shader_);
106 }
107 if (geometry_shader_code != NULL) {
108 glAttachShader(program_, geometry_shader_);
109 }
110 if (fragment_shader_code != NULL) {
111 glAttachShader(program_, fragment_shader_);
112 }
113 glLinkProgram(program_);
114 if (ValidateProgram(program_) == false) {
115 return false;
116 }
117
118 // Mark shader objects as deletable.
119 // They will be released as soon as program is deleted.
120 if (vertex_shader_code != NULL) {
121 glDeleteShader(vertex_shader_);
122 }
123 if (geometry_shader_code != NULL) {
124 glDeleteShader(geometry_shader_);
125 }
126 if (fragment_shader_code != NULL) {
127 glDeleteShader(fragment_shader_);
128 }
129
130 compiled_ = true;
131 return true;
132 }
133
ReleaseProgram()134 void ShaderWrapper::ReleaseProgram()
135 {
136 if (compiled_) {
137 glDeleteProgram(program_);
138 compiled_ = false;
139 }
140 }
141
ValidateShader(GLuint shader_index)142 bool ShaderWrapper::ValidateShader(GLuint shader_index)
143 {
144 GLint result = GL_FALSE;
145 int info_log_length;
146 glGetShaderiv(shader_index, GL_COMPILE_STATUS, &result);
147 if (result == GL_FALSE) {
148 glGetShaderiv(shader_index, GL_INFO_LOG_LENGTH, &info_log_length);
149 if (info_log_length > 0) {
150 std::vector<char> error_message(info_log_length + 1);
151 glGetShaderInfoLog(shader_index, info_log_length, NULL,
152 &error_message[0]);
153 PrintError("Shader error: %s\n", &error_message[0]);
154 }
155 return false;
156 }
157 return true;
158 }
159
ValidateProgram(GLuint program_index)160 bool ShaderWrapper::ValidateProgram(GLuint program_index)
161 {
162 GLint result = GL_FALSE;
163 int info_log_length;
164 glGetProgramiv(program_index, GL_LINK_STATUS, &result);
165 if (result == GL_FALSE) {
166 glGetProgramiv(program_index, GL_INFO_LOG_LENGTH, &info_log_length);
167 if (info_log_length > 0) {
168 std::vector<char> error_message(info_log_length + 1);
169 glGetShaderInfoLog(program_index, info_log_length, NULL,
170 &error_message[0]);
171 PrintError("Shader error: %s\n", &error_message[0]);
172 }
173 return false;
174 }
175 return true;
176 }
177
178 } // namespace three::glsl
179
180 } // namespace three
181