├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTING ├── GLSLProgram.cpp ├── GLSLProgram.h ├── LICENSE ├── README.md ├── SvCMFCUI.h ├── doc └── sample.JPG └── gl_path_rendering_CMYK.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build_cmake 2 | 3 | ################# 4 | ## Eclipse 5 | ################# 6 | 7 | *.pydevproject 8 | .project 9 | .metadata 10 | bin/ 11 | tmp/ 12 | *.tmp 13 | *.bak 14 | *.swp 15 | *~.nib 16 | local.properties 17 | .classpath 18 | .settings/ 19 | .loadpath 20 | 21 | # External tool builders 22 | .externalToolBuilders/ 23 | 24 | # Locally stored "Eclipse launch configurations" 25 | *.launch 26 | 27 | # CDT-specific 28 | .cproject 29 | 30 | # PDT-specific 31 | .buildpath 32 | 33 | 34 | ################# 35 | ## Visual Studio 36 | ################# 37 | 38 | ## Ignore Visual Studio temporary files, build results, and 39 | ## files generated by popular Visual Studio add-ons. 40 | 41 | # User-specific files 42 | *.vcxproj 43 | *.filters 44 | *.sln 45 | *.user 46 | *.suo 47 | *.user 48 | *.sln.docstates 49 | 50 | # Build results 51 | [Dd]ebug/ 52 | [Rr]elease/ 53 | *_i.c 54 | *_p.c 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.vspscc 69 | .builds 70 | *.dotCover 71 | 72 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 73 | #packages/ 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | 82 | # Visual Studio profiler 83 | *.psess 84 | *.vsp 85 | 86 | # ReSharper is a .NET coding add-in 87 | _ReSharper* 88 | 89 | # Installshield output folder 90 | [Ee]xpress 91 | 92 | # DocProject is a documentation generator add-in 93 | DocProject/buildhelp/ 94 | DocProject/Help/*.HxT 95 | DocProject/Help/*.HxC 96 | DocProject/Help/*.hhc 97 | DocProject/Help/*.hhk 98 | DocProject/Help/*.hhp 99 | DocProject/Help/Html2 100 | DocProject/Help/html 101 | 102 | # Click-Once directory 103 | publish 104 | 105 | # Others 106 | [Bb]in 107 | [Oo]bj 108 | sql 109 | TestResults 110 | *.Cache 111 | ClientBin 112 | stylecop.* 113 | ~$* 114 | *.dbmdl 115 | Generated_Code #added for RIA/Silverlight projects 116 | 117 | # Backup & report files from converting an old project file to a newer 118 | # Visual Studio version. Backup files are not needed, because we have git ;-) 119 | _UpgradeReport_Files/ 120 | Backup*/ 121 | UpgradeLog*.XML 122 | 123 | 124 | 125 | ############ 126 | ## Windows 127 | ############ 128 | 129 | # Windows image file caches 130 | Thumbs.db 131 | 132 | # Folder config file 133 | Desktop.ini 134 | 135 | 136 | ############# 137 | ## Python 138 | ############# 139 | 140 | *.py[co] 141 | 142 | # Packages 143 | *.egg 144 | *.egg-info 145 | dist 146 | build 147 | eggs 148 | parts 149 | bin 150 | var 151 | sdist 152 | develop-eggs 153 | .installed.cfg 154 | 155 | # Installer logs 156 | pip-log.txt 157 | 158 | # Unit test / coverage reports 159 | .coverage 160 | .tox 161 | 162 | #Translations 163 | *.mo 164 | 165 | #Mr Developer 166 | .mr.developer.cfg 167 | 168 | # Mac crap 169 | .DS_Store 170 | 171 | #specific to the project 172 | cmake_built 173 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | set(PROJNAME gl_path_rendering_CMYK) 3 | Project(${PROJNAME}) 4 | Message(STATUS "-------------------------------") 5 | Message(STATUS "Processing Project ${PROJNAME}:") 6 | 7 | ##################################################################################### 8 | # look for nvpro_core 1) as a sub-folder 2) at some other locations 9 | # this cannot be put anywhere else since we still didn't find setup.cmake yet 10 | # 11 | if(NOT BASE_DIRECTORY) 12 | 13 | find_path(BASE_DIRECTORY 14 | NAMES nvpro_core/cmake/setup.cmake 15 | PATHS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../.. 16 | REQUIRED 17 | DOC "Directory containing nvpro_core" 18 | ) 19 | endif() 20 | if(EXISTS ${BASE_DIRECTORY}/nvpro_core/cmake/setup.cmake) 21 | include(${BASE_DIRECTORY}/nvpro_core/cmake/setup.cmake) 22 | else() 23 | message(FATAL_ERROR "could not find base directory, please set BASE_DIRECTORY to folder containing nvpro_core") 24 | endif() 25 | 26 | _add_project_definitions(${PROJNAME}) 27 | 28 | ##################################################################################### 29 | # additions from packages needed for this sample 30 | # add refs in LIBRARIES_OPTIMIZED 31 | # add refs in LIBRARIES_DEBUG 32 | # add files in PACKAGE_SOURCE_FILES 33 | # 34 | _add_package_OpenGL() 35 | _add_package_ImGUI() 36 | 37 | ##################################################################################### 38 | # process the rest of some cmake code that needs to be done *after* the packages add 39 | _add_nvpro_core_lib() 40 | 41 | ##################################################################################### 42 | # Source files for this project 43 | # 44 | file(GLOB SOURCE_FILES *.cpp *.hpp *.inl *.h *.c) 45 | 46 | ##################################################################################### 47 | # Executable 48 | # 49 | if(WIN32 AND NOT GLUT_FOUND) 50 | add_definitions(/wd4267) #remove size_t to int warning 51 | add_definitions(/wd4996) #remove printf warning 52 | add_definitions(/wd4244) #remove double to float conversion warning 53 | add_definitions(/wd4305) #remove double to float truncation warning 54 | endif() 55 | add_executable(${PROJNAME} ${SOURCE_FILES} ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES}) 56 | 57 | ##################################################################################### 58 | # common source code needed for this sample 59 | # 60 | source_group(common FILES 61 | ${COMMON_SOURCE_FILES} 62 | ${PACKAGE_SOURCE_FILES} 63 | ) 64 | ##################################################################################### 65 | # Linkage 66 | # 67 | target_link_libraries(${PROJNAME} optimized 68 | ${LIBRARIES_OPTIMIZED} 69 | ${PLATFORM_LIBRARIES} 70 | nvpro_core 71 | ) 72 | target_link_libraries(${PROJNAME} debug 73 | ${LIBRARIES_DEBUG} 74 | ${PLATFORM_LIBRARIES} 75 | nvpro_core 76 | ) 77 | 78 | ##################################################################################### 79 | # copies binaries that need to be put next to the exe files (ZLib, etc.) 80 | # 81 | _finalize_target( ${PROJNAME} ) 82 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | https://developercertificate.org/ 2 | 3 | Developer Certificate of Origin 4 | Version 1.1 5 | 6 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | 12 | Developer's Certificate of Origin 1.1 13 | 14 | By making a contribution to this project, I certify that: 15 | 16 | (a) The contribution was created in whole or in part by me and I 17 | have the right to submit it under the open source license 18 | indicated in the file; or 19 | 20 | (b) The contribution is based upon previous work that, to the best 21 | of my knowledge, is covered under an appropriate open source 22 | license and I have the right under that license to submit that 23 | work with modifications, whether created in whole or in part 24 | by me, under the same open source license (unless I am 25 | permitted to submit under a different license), as indicated 26 | in the file; or 27 | 28 | (c) The contribution was provided directly to me by some other 29 | person who certified (a), (b) or (c) and I have not modified 30 | it. 31 | 32 | (d) I understand and agree that this project and the contribution 33 | are public and that a record of the contribution (including all 34 | personal information I submit with it, including my sign-off) is 35 | maintained indefinitely and may be redistributed consistent with 36 | this project or the open source license(s) involved. -------------------------------------------------------------------------------- /GLSLProgram.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-FileCopyrightText: Copyright (c) 2018-2021 NVIDIA CORPORATION 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | //-------------------------------------------------------------------- 20 | 21 | #include 22 | #include 23 | #include // for strcpy() etc. 24 | #include 25 | #include "nvh/nvprint.hpp" 26 | #include "GLSLProgram.h" 27 | 28 | char const * GLSLProgram::incPaths[] = {"/"}; 29 | 30 | bool GLSLProgram::setIncludeFromFile(const char *includeName, const char* filename) 31 | { 32 | char tmpstr[200]; 33 | sprintf(tmpstr, "%s/%s", filename, includeName); 34 | char * incStr = readTextFile(tmpstr); 35 | if(!incStr) 36 | return false; 37 | sprintf(tmpstr, "/%s", includeName); 38 | glNamedStringARB(GL_SHADER_INCLUDE_ARB, GLint(strlen(tmpstr)), tmpstr, GLint(strlen(incStr)), incStr); 39 | return false; 40 | } 41 | void GLSLProgram::setIncludeFromString(const char *includeName, const char* str) 42 | { 43 | char tmpstr[200]; 44 | sprintf(tmpstr, "/%s", includeName); 45 | glNamedStringARB(GL_SHADER_INCLUDE_ARB, GLint(strlen(tmpstr)), tmpstr, GLint(strlen(str)), str); 46 | } 47 | 48 | GLSLProgram::GLSLProgram(const char*progName) : mProg(0) 49 | { 50 | curVSName = NULL; 51 | curFSName = NULL; 52 | curGSName = NULL; 53 | curProgName = NULL; 54 | if(progName) 55 | { 56 | curProgName = (char*)malloc(strlen(progName)+1); 57 | strncpy(curProgName, progName, strlen(progName)+1); 58 | } 59 | } 60 | 61 | GLSLProgram::GLSLProgram(const char *vsource, const char *fsource) 62 | { 63 | curVSName = NULL; 64 | curFSName = NULL; 65 | curGSName = NULL; 66 | compileProgram(vsource, 0, fsource); 67 | } 68 | 69 | GLSLProgram::GLSLProgram(const char *vsource, const char *gsource, const char *fsource, 70 | GLenum gsInput, GLenum gsOutput, int maxVerts) 71 | { 72 | mProg = compileProgram(vsource, gsource, fsource, gsInput, gsOutput, maxVerts); 73 | } 74 | 75 | void 76 | GLSLProgram::setShaderNames(const char*ProgName, const char *VSName,const char *GSName,const char *FSName) 77 | { 78 | if(VSName) 79 | { 80 | if(curVSName) free(curVSName); 81 | curVSName = (char*)malloc(strlen(VSName)+1); 82 | strncpy(curVSName, VSName, strlen(VSName)+1); 83 | } 84 | if(FSName) 85 | { 86 | if(curFSName) free(curFSName); 87 | curFSName = (char*)malloc(strlen(FSName)+1); 88 | strncpy(curFSName, FSName, strlen(FSName)+1); 89 | } 90 | if(GSName) 91 | { 92 | if(curGSName) free(curGSName); 93 | curGSName = (char*)malloc(strlen(GSName)+1); 94 | strncpy(curGSName, GSName, strlen(GSName)+1); 95 | } 96 | if(ProgName) 97 | { 98 | if(curProgName) free(curProgName); 99 | curProgName = (char*)malloc(strlen(ProgName)+1); 100 | strncpy(curProgName, ProgName, strlen(ProgName)+1); 101 | } 102 | } 103 | 104 | GLuint 105 | GLSLProgram::compileProgramFromFiles(const char *vFilename, const char *gFilename, const char *fFilename, 106 | GLenum gsInput, GLenum gsOutput, int maxVerts) 107 | { 108 | char *vsource = readTextFile(vFilename); 109 | char *gsource = 0; 110 | if (mProg) { 111 | glDeleteProgram(mProg); 112 | } 113 | if (gFilename) { 114 | gsource = readTextFile(gFilename); 115 | } 116 | char *fsource = readTextFile(fFilename); 117 | if(vsource) 118 | { 119 | GLSLProgram::setShaderNames(NULL, vFilename, gFilename, fFilename); 120 | mProg = compileProgram(vsource, gsource, fsource, gsInput, gsOutput, maxVerts); 121 | delete [] vsource; 122 | if (gsource) delete [] gsource; 123 | delete [] fsource; 124 | return mProg; 125 | } 126 | return 0; 127 | } 128 | 129 | GLSLProgram::~GLSLProgram() 130 | { 131 | if (mProg) { 132 | glDeleteProgram(mProg); 133 | } 134 | if (curVSName) free(curVSName); 135 | if (curFSName) free(curFSName); 136 | if (curGSName) free(curGSName); 137 | if (curProgName) free(curProgName); 138 | } 139 | 140 | void 141 | GLSLProgram::enable() 142 | { 143 | glUseProgram(mProg); 144 | } 145 | 146 | void 147 | GLSLProgram::disable() 148 | { 149 | glUseProgram(0); 150 | } 151 | 152 | void 153 | GLSLProgram::setUniform1f(const char *name, float value) 154 | { 155 | GLint loc = glGetUniformLocation(mProg, name); 156 | if (loc >= 0) { 157 | glUniform1f(loc, value); 158 | } else { 159 | #if _DEBUG 160 | LOGE("Error setting parameter '%s'\n", name); 161 | #endif 162 | } 163 | } 164 | 165 | void 166 | GLSLProgram::setUniform2f(const char *name, float x, float y) 167 | { 168 | GLint loc = glGetUniformLocation(mProg, name); 169 | if (loc >= 0) { 170 | glUniform2f(loc, x, y); 171 | } else { 172 | #if _DEBUG 173 | LOGE("Error setting parameter '%s'\n", name); 174 | #endif 175 | } 176 | } 177 | 178 | void 179 | GLSLProgram::setUniform3f(const char *name, float x, float y, float z) 180 | { 181 | GLint loc = glGetUniformLocation(mProg, name); 182 | if (loc >= 0) { 183 | glUniform3f(loc, x, y, z); 184 | } else { 185 | #if _DEBUG 186 | LOGE("Error setting parameter '%s'\n", name); 187 | #endif 188 | } 189 | } 190 | 191 | void 192 | GLSLProgram::setUniform4f(const char *name, float x, float y, float z, float w) 193 | { 194 | GLint loc = glGetUniformLocation(mProg, name); 195 | if (loc >= 0) { 196 | glUniform4f(loc, x, y, z, w); 197 | } else { 198 | #if _DEBUG 199 | LOGE("Error setting parameter '%s'\n", name); 200 | #endif 201 | } 202 | } 203 | 204 | void 205 | GLSLProgram::setUniformMatrix4fv(const GLchar *name, GLfloat *m, bool transpose) 206 | { 207 | GLint loc = glGetUniformLocation(mProg, name); 208 | if (loc >= 0) { 209 | glUniformMatrix4fv(loc, 1, transpose, m); 210 | } else { 211 | #if _DEBUG 212 | LOGE("Error setting parameter '%s'\n", name); 213 | #endif 214 | } 215 | } 216 | 217 | void 218 | GLSLProgram::setUniformfv(const GLchar *name, GLfloat *v, int elementSize, int count) 219 | { 220 | GLint loc = glGetUniformLocation(mProg, name); 221 | if (loc == -1) { 222 | #ifdef _DEBUG 223 | LOGE("Error setting parameter '%s'\n", name); 224 | #endif 225 | return; 226 | } 227 | 228 | switch (elementSize) { 229 | case 1: 230 | glUniform1fv(loc, count, v); 231 | break; 232 | case 2: 233 | glUniform2fv(loc, count, v); 234 | break; 235 | case 3: 236 | glUniform3fv(loc, count, v); 237 | break; 238 | case 4: 239 | glUniform4fv(loc, count, v); 240 | break; 241 | } 242 | } 243 | 244 | void 245 | GLSLProgram::setUniform3i(const char *name, int x, int y, int z) 246 | { 247 | GLint loc = glGetUniformLocation(mProg, name); 248 | if (loc >= 0) { 249 | glUniform3i(loc, x, y, z); 250 | } else { 251 | #if _DEBUG 252 | LOGE("Error setting parameter '%s'\n", name); 253 | #endif 254 | } 255 | } 256 | 257 | void 258 | GLSLProgram::setUniform1i(const char *name, int x) 259 | { 260 | GLint loc = glGetUniformLocation(mProg, name); 261 | if (loc >= 0) { 262 | glUniform1i(loc, x); 263 | } else { 264 | #if _DEBUG 265 | LOGE("Error setting parameter '%s'\n", name); 266 | #endif 267 | } 268 | } 269 | 270 | void 271 | GLSLProgram::setUniform2i(const char *name, int x, int y) 272 | { 273 | GLint loc = glGetUniformLocation(mProg, name); 274 | if (loc >= 0) { 275 | glUniform2i(loc, x, y); 276 | } else { 277 | #if _DEBUG 278 | LOGE("Error setting parameter '%s'\n", name); 279 | #endif 280 | } 281 | } 282 | 283 | void 284 | GLSLProgram::bindTexture(const char *name, GLuint tex, GLenum target, GLint unit) 285 | { 286 | GLint loc = glGetUniformLocation(mProg, name); 287 | if (loc >= 0) { 288 | glActiveTexture(GL_TEXTURE0 + unit); 289 | glBindTexture(target, tex); 290 | glUseProgram(mProg); 291 | glUniform1i(loc, unit); 292 | glActiveTexture(GL_TEXTURE0); 293 | } else { 294 | #if _DEBUG 295 | LOGE("Error binding texture '%s'\n", name); 296 | #endif 297 | } 298 | } 299 | void 300 | GLSLProgram::bindImage(const char *name, GLint unit, GLuint tex, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) 301 | { 302 | GLint loc = glGetUniformLocation(mProg, name); 303 | if (loc >= 0) { 304 | glBindImageTexture(unit, tex, level, layered, layer, access, format); 305 | glUseProgram(mProg); 306 | glUniform1i(loc, unit); 307 | } else { 308 | #if _DEBUG 309 | LOGE("Error binding texture '%s'\n", name); 310 | #endif 311 | } 312 | } 313 | 314 | 315 | GLuint 316 | GLSLProgram::compileProgram(const char *vsource, const char *gsource, const char *fsource, 317 | GLenum gsInput, GLenum gsOutput, int maxVerts) 318 | { 319 | bool bErrors = false; 320 | GLint success = 0; 321 | char temp[1024]; 322 | GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 323 | GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 324 | 325 | mProg = glCreateProgram(); 326 | 327 | if(vsource) 328 | { 329 | glShaderSource(vertexShader, 1, &vsource, 0); 330 | glCompileShaderIncludeARB(vertexShader, 1, incPaths,NULL); 331 | glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); 332 | if (!success) { 333 | glGetShaderInfoLog(vertexShader, 1024, 0, temp); 334 | LOGE("%s: Failed to compile VtxShader:\n%s\n", curVSName ? curVSName:"VSNoname", temp); 335 | glDeleteShader(vertexShader); 336 | vertexShader = 0; 337 | bErrors = true; 338 | } 339 | else 340 | { 341 | glAttachShader(mProg, vertexShader); 342 | glDeleteShader(vertexShader); 343 | } 344 | } 345 | // NOTE: had some issues using include paths with https://www.opengl.org/registry/specs/ARB/shading_language_include.txt 346 | glShaderSource(fragmentShader, 1, &fsource, 0); 347 | glCompileShaderIncludeARB(fragmentShader, 1, incPaths,NULL); 348 | glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); 349 | if (!success) { 350 | glGetShaderInfoLog(fragmentShader, 1024, 0, temp); 351 | LOGE("%s: Failed to compile FragShader:\n%s\n", curFSName ? curFSName:"VSNoname", temp); 352 | glDeleteShader(fragmentShader); 353 | fragmentShader = 0; 354 | bErrors = true; 355 | } 356 | else 357 | { 358 | glAttachShader(mProg, fragmentShader); 359 | glDeleteShader(fragmentShader); 360 | } 361 | if (gsource) { 362 | GLuint geomShader = glCreateShader(GL_GEOMETRY_SHADER); 363 | // NOTE: had some issues using include paths with https://www.opengl.org/registry/specs/ARB/shading_language_include.txt 364 | glShaderSource(geomShader, 1, &gsource, 0); 365 | glCompileShaderIncludeARB(geomShader, 1, incPaths,NULL); 366 | glGetShaderiv(geomShader, GL_COMPILE_STATUS, &success); 367 | if (!success) { 368 | glGetShaderInfoLog(geomShader, 1024, 0, temp); 369 | LOGE("%s: Failed to compile GShader:\n%s\n", curGSName ? curGSName:"VSNoname", temp); 370 | glDeleteShader(geomShader); 371 | geomShader = 0; 372 | bErrors = true; 373 | } 374 | else 375 | { 376 | glAttachShader(mProg, geomShader); 377 | glDeleteShader(geomShader); 378 | } 379 | 380 | //glProgramParameteri(mProg, GL_GEOMETRY_INPUT_TYPE, gsInput); 381 | //glProgramParameteri(mProg, GL_GEOMETRY_OUTPUT_TYPE, gsOutput); 382 | //glProgramParameteri(mProg, GL_GEOMETRY_VERTICES_OUT, maxVerts); 383 | } 384 | 385 | if(bErrors) 386 | { 387 | glDeleteProgram(mProg); 388 | mProg = 0; 389 | return 0; 390 | } 391 | glLinkProgram(mProg); 392 | 393 | // check if program linked 394 | glGetProgramiv(mProg, GL_LINK_STATUS, &success); 395 | if (!success) { 396 | glGetProgramInfoLog(mProg, 1024, 0, temp); 397 | LOGE("%s: Failed to link program:\n%s\n", curProgName ?curProgName:"Noname", temp); 398 | glDeleteProgram(mProg); 399 | mProg = 0; 400 | return 0; 401 | } 402 | 403 | return mProg; 404 | } 405 | 406 | char * 407 | GLSLProgram::readTextFile(const char *filename) 408 | { 409 | if (!filename) return 0; 410 | 411 | FILE *fp = 0; 412 | if (!(fp = fopen(filename, "r"))) 413 | { 414 | LOGE("Cannot open \"%s\" for read!\n", filename); 415 | return 0; 416 | } 417 | 418 | fseek(fp, 0L, SEEK_END); // seek to end of file 419 | long size = ftell(fp); // get file length 420 | rewind(fp); // rewind to start of file 421 | 422 | char * buf = new char[size+1]; 423 | 424 | size_t bytes; 425 | bytes = fread(buf, 1, size, fp); 426 | 427 | buf[bytes] = 0; 428 | 429 | fclose(fp); 430 | return buf; 431 | } 432 | -------------------------------------------------------------------------------- /GLSLProgram.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-FileCopyrightText: Copyright (c) 2018-2021 NVIDIA CORPORATION 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | //-------------------------------------------------------------------- 20 | 21 | // Simple class to contain GLSL shaders/programs 22 | 23 | #ifndef GLSL_PROGRAM_H 24 | #define GLSL_PROGRAM_H 25 | 26 | #include 27 | #include 28 | 29 | class GLSLProgram 30 | { 31 | public: 32 | // construct program from strings 33 | GLSLProgram(const char*progName=NULL); 34 | GLSLProgram(const char *vsource, const char *fsource); 35 | GLSLProgram(const char *vsource, const char *gsource, const char *fsource, 36 | GLenum gsInput = GL_POINTS, GLenum gsOutput = GL_TRIANGLE_STRIP, int maxVerts=4); 37 | 38 | ~GLSLProgram(); 39 | 40 | void enable(); 41 | void disable(); 42 | 43 | void setUniform1f(const GLchar *name, GLfloat x); 44 | void setUniform2f(const GLchar *name, GLfloat x, GLfloat y); 45 | void setUniform2fv(const GLchar *name, float *v) { setUniformfv(name, v, 2, 1); } 46 | void setUniform3f(const GLchar *name, float x, float y, float z); 47 | void setUniform3fv(const GLchar *name, float *v) { setUniformfv(name, v, 3, 1); } 48 | void setUniform4f(const GLchar *name, float x, float y=0.0f, float z=0.0f, float w=0.0f); 49 | void setUniformfv(const GLchar *name, GLfloat *v, int elementSize, int count=1); 50 | void setUniformMatrix4fv(const GLchar *name, GLfloat *m, bool transpose); 51 | 52 | void setUniform1i(const GLchar *name, GLint x); 53 | void setUniform2i(const GLchar *name, GLint x, GLint y); 54 | void setUniform3i(const GLchar *name, int x, int y, int z); 55 | 56 | void bindTexture(const GLchar *name, GLuint tex, GLenum target, GLint unit); 57 | void bindImage (const GLchar *name, GLint unit, GLuint tex, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); 58 | 59 | inline GLuint getProgId() { return mProg; } 60 | 61 | GLuint compileProgram(const char *vsource, const char *gsource, const char *fsource, 62 | GLenum gsInput = GL_POINTS, GLenum gsOutput = GL_TRIANGLE_STRIP, int maxVerts=4); 63 | GLuint compileProgramFromFiles(const char *vFilename, const char *gFilename, const char *fFilename, 64 | GLenum gsInput = GL_POINTS, GLenum gsOutput = GL_TRIANGLE_STRIP, int maxVerts=4); 65 | void setShaderNames(const char*ProgName, const char *VSName=NULL,const char *GSName=NULL,const char *FSName=NULL); 66 | static bool setIncludeFromFile(const char *includeName, const char* filename); 67 | static void setIncludeFromString(const char *includeName, const char* str); 68 | private: 69 | static char *readTextFile(const char *filename); 70 | char *curVSName, *curFSName, *curGSName, *curProgName; 71 | 72 | GLuint mProg; 73 | static char const* incPaths[]; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gl_path_rendering_CMYK 2 | 3 | This sample shows how to use NVIDIA path rendering extension. 4 | 5 | It also exposes it through FBO (Frame-buffer-objects) and shows how to work on CMYK-Alpha format. 6 | 7 | Additional repositories needed: 8 | * nvpro_core 9 | cmake can either locate them from this folder, or locate them if they are somewhere else in your computer. 10 | 11 | ![Example](https://github.com/nvpro-samples/gl_path_rendering_CMYK/blob/master/doc/sample.JPG) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SvCMFCUI.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-FileCopyrightText: Copyright (c) 2018-2021 NVIDIA CORPORATION 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | //-------------------------------------------------------------------- 20 | #ifdef USESVCUI 21 | #include "ISvcUI.h" 22 | #ifdef EXTERNSVCUI 23 | extern nvSvc::ISvcFactory* g_pFactUI; 24 | extern IWindowHandler * g_pWinHandler; 25 | extern IWindowConsole* g_pConsole; 26 | extern IWindowLog* g_pLog; 27 | extern IProgressBar* g_pProgress; 28 | extern IWindowFolding* g_pToggleContainer; 29 | extern void addToggleKeyToMFCUI(char c, bool* target, const char* desc); 30 | extern void shutdownMFCUI(); 31 | extern void initMFCUIBase(int x=0, int y=600, int w=400, int h=100); 32 | extern void logMFCUI(int level, const char * txt); 33 | extern void flushMFCUIToggle(int key); 34 | #else 35 | nvSvc::ISvcFactory* g_pFactUI = NULL; 36 | IWindowHandler * g_pWinHandler = NULL; 37 | IWindowConsole* g_pConsole = NULL; 38 | IWindowLog* g_pLog = NULL; 39 | IProgressBar* g_pProgress = NULL; 40 | 41 | IWindowFolding* g_pToggleContainer = NULL; 42 | void addToggleKeyToMFCUI(char c, bool* target, const char* desc) 43 | { 44 | if(!g_pToggleContainer) 45 | return; 46 | g_pToggleContainer->UnFold(0); 47 | g_pWinHandler->VariableBind(g_pWinHandler->CreateCtrlCheck((LPCSTR)c, desc, g_pToggleContainer), target); 48 | g_pToggleContainer->UnFold(); 49 | } 50 | 51 | void shutdownMFCUI() 52 | { 53 | g_pConsole = NULL; 54 | g_pLog = NULL; 55 | if(g_pWinHandler) g_pWinHandler->DestroyAll(); 56 | UISERVICE_UNLOAD(g_pFactUI, g_pWinHandler); 57 | } 58 | 59 | //------------------------------------------------------------------------------ 60 | // Setup the base layout of the UI 61 | // the rest can be done outside, depending on the sample's needs 62 | void initMFCUIBase(int x=0, int y=600, int w=400, int h=100) 63 | { 64 | UISERVICE_LOAD(g_pFactUI, g_pWinHandler); 65 | if(g_pWinHandler) 66 | { 67 | // a Log window is a line-by-line logging, with possible icons for message levels 68 | g_pLog= g_pWinHandler->CreateWindowLog("LOG", "Log"); 69 | g_pLog->SetVisible()->SetLocation(x,y)->SetSize(w-(w*30/100),h); 70 | (g_pToggleContainer = g_pWinHandler->CreateWindowFolding("TOGGLES", "Toggles", NULL)) 71 | ->SetLocation(x+(w*70/100), y) 72 | ->SetSize(w*30/100, h) 73 | ->SetVisible(); 74 | // Console is a window in which you can write and capture characters the user typed... 75 | //g_pConsole = g_pWinHandler->CreateWindowConsole("CONSOLE", "Console"); 76 | //g_pConsole->SetVisible();//->SetLocation(0,m_winSize[1]+32)->SetSize(m_winSize[0],200); 77 | // Show and update this control when doing long load/computation... for example 78 | g_pProgress = g_pWinHandler->CreateWindowProgressBar("PROG", "Loading", NULL); 79 | g_pProgress->SetVisible(0); 80 | } 81 | } 82 | 83 | void logMFCUI(int level, const char * txt) 84 | { 85 | if(g_pLog) 86 | g_pLog->AddMessage(level, txt); 87 | } 88 | 89 | extern std::map g_toggleMap; 90 | void flushMFCUIToggle(int key) 91 | { 92 | std::map::iterator it = g_toggleMap.find(key); 93 | if(it != g_toggleMap.end()) 94 | g_pWinHandler->VariableFlush(it->second); 95 | } 96 | #endif 97 | #endif 98 | -------------------------------------------------------------------------------- /doc/sample.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nvpro-samples/gl_path_rendering_CMYK/c7e625792102e4b01f249d8c0bf6e52adddc01d0/doc/sample.JPG -------------------------------------------------------------------------------- /gl_path_rendering_CMYK.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-FileCopyrightText: Copyright (c) 2018-2021 NVIDIA CORPORATION 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | //-------------------------------------------------------------------- 20 | #include 21 | #include 22 | 23 | #include "GLSLProgram.h" 24 | #include "nvgl/contextwindow_gl.hpp" 25 | #include "nvgl/extensions_gl.hpp" 26 | #include "nvgl/profiler_gl.hpp" 27 | #include "nvh/appwindowcamerainertia.hpp" 28 | #include 29 | #include 30 | #include 31 | 32 | // 33 | // Camera animation: captured using '1' in the sample. Then copy and paste... 34 | // 35 | struct CameraAnim 36 | { 37 | glm::vec3 eye, focus; 38 | }; 39 | static CameraAnim s_cameraAnim[] = { 40 | {glm::vec3(-1.26, 0.47, 1.01), glm::vec3(-0.96, 0.47, 0.00)}, 41 | {glm::vec3(0.38, 0.34, 0.43), glm::vec3(0.37, 0.35, 0.14)}, 42 | {glm::vec3(1.58, 0.54, 0.65), glm::vec3(0.65, 0.56, -0.06)}, 43 | {glm::vec3(1.07, -1.91, 4.75), glm::vec3(0.07, -0.50, 0.22)}, 44 | {glm::vec3(-3.41, 0.39, 2.76), glm::vec3(-0.96, -0.33, -0.28)}, 45 | {glm::vec3(-0.94, -0.15, 0.69), glm::vec3(-0.96, -0.33, -0.28)}, 46 | {glm::vec3(-0.25, -0.18, 0.67), glm::vec3(-0.27, -0.36, -0.29)}, 47 | {glm::vec3(0.79, -0.26, 0.66), glm::vec3(0.77, -0.43, -0.30)}, 48 | {glm::vec3(0.38, -0.98, 0.79), glm::vec3(0.36, -1.15, -0.16)}, 49 | {glm::vec3(-1.46, -1.48, 0.05), glm::vec3(-0.58, -1.12, -0.41)}, 50 | {glm::vec3(-1.64, -0.70, 0.30), glm::vec3(-0.76, -0.35, -0.16)}, 51 | {glm::vec3(-1.13, -0.66, 1.39), glm::vec3(-0.76, -0.35, -0.16)}, 52 | {glm::vec3(-0.20, -0.65, 3.05), glm::vec3(-0.20, -0.45, -0.11)}, 53 | {glm::vec3(0.00, 0.00, 3.00), glm::vec3(0.00, 0.00, 0.00)}, //14 items 54 | }; 55 | static int s_cameraAnimItem = 0; 56 | static int s_cameraAnimItems = 14; 57 | #define ANIMINTERVALL 1.5f 58 | static float s_cameraAnimIntervals = ANIMINTERVALL; 59 | static bool s_bCameraAnim = true; 60 | static bool s_helpText = false; 61 | 62 | static nvgl::ProfilerGL s_profiler; 63 | static double s_statsCpuTime = 0; 64 | static double s_statsGpuTime = 0; 65 | 66 | #define PROFILE_SECTION(name) nvgl::ProfilerGL::Section _tempTimer(s_profiler, name); 67 | 68 | //----------------------------------------------------------------------------- 69 | // Derive the Window for this sample 70 | //----------------------------------------------------------------------------- 71 | class MyWindow : public AppWindowCameraInertia 72 | { 73 | bool m_validated; 74 | 75 | public: 76 | ImGuiH::Registry m_guiRegistry; 77 | nvgl::ContextWindow m_contextWindowGL; 78 | 79 | MyWindow() 80 | : m_validated(false) 81 | { 82 | } 83 | 84 | bool open(int posX, int posY, int width, int height, const char* title, const nvgl::ContextWindowCreateInfo& context); 85 | void renderScene(); 86 | void processUI(int width, int height, double dt); 87 | 88 | virtual void onWindowClose() override; 89 | virtual void onWindowResize(int w, int h) override; 90 | //virtual void motion(int x, int y) override; 91 | //virtual void mousewheel(short delta) override; 92 | //virtual void mouse(NVPWindow::MouseButton button, ButtonAction action, int mods, int x, int y) override; 93 | //virtual void menu(int m) override; 94 | virtual void onKeyboard(MyWindow::KeyCode key, ButtonAction action, int mods, int x, int y) override; 95 | virtual void onKeyboardChar(unsigned char key, int mods, int x, int y) override; 96 | //virtual void idle() override; 97 | virtual void onWindowRefresh() override; 98 | }; 99 | 100 | ///////////////////////////////////////////////////////////////////////// 101 | // Cst color 102 | static const char* g_glslv_WVP_Position = 103 | "#version 330\n" 104 | "#extension GL_ARB_separate_shader_objects : enable\n" 105 | "uniform mat4 mWVP;\n" 106 | "layout(location=0) in vec3 P;\n" 107 | "out gl_PerVertex {\n" 108 | " vec4 gl_Position;\n" 109 | "};\n" 110 | "void main() {\n" 111 | " gl_Position = mWVP * vec4(P, 1.0);\n" 112 | "}\n"; 113 | static const char* g_glslf_OneMinusCMYK_A = 114 | "#version 330\n" 115 | "#extension GL_ARB_separate_shader_objects : enable\n" 116 | "uniform vec4 CMYK;\n" 117 | "uniform float alpha;\n" 118 | "layout(location=0) out vec4 outCMYA;\n" 119 | "layout(location=1) out vec4 outKA;\n" 120 | "void main() {\n" 121 | " outCMYA = vec4(1.0-CMYK.xyz, alpha);\n" 122 | " outKA = vec4(1.0-CMYK.w,1,1, alpha);\n" 123 | "}\n"; 124 | static const char* g_glslf_RGBA = 125 | "#version 330\n" 126 | "#extension GL_ARB_separate_shader_objects : enable\n" 127 | "uniform vec4 RGBA;\n" 128 | "layout(location=0) out vec4 outRGBA;\n" 129 | "void main() {\n" 130 | " outRGBA = RGBA;\n" 131 | "}\n"; 132 | 133 | ///////////////////////////////////////////////////////////////////////// 134 | // FBO resolve 135 | 136 | static const char* g_glslv_Tc = 137 | "#version 330\n" 138 | "#extension GL_ARB_separate_shader_objects : enable\n" 139 | "uniform ivec2 viewportSz;\n" 140 | "layout(location=0) in ivec2 P;\n" 141 | "layout(location=0) out vec2 TcOut;\n" 142 | "out gl_PerVertex {\n" 143 | " vec4 gl_Position;\n" 144 | "};\n" 145 | "void main() {\n" 146 | " TcOut = vec2(P);\n" 147 | " gl_Position = vec4(vec2(P)/vec2(viewportSz)*2.0 - 1.0, 0.0, 1.0);\n" 148 | "}\n"; 149 | 150 | #define CMYK2RGB \ 151 | "vec3 OneMinusCMYK2RGB(in vec4 CMYK) {\n" \ 152 | " vec3 cmy = vec3(1-min(1.0, (CMYK.x)+(CMYK.w)),\n" \ 153 | " 1-min(1.0, (CMYK.y)+(CMYK.w)),\n" \ 154 | " 1-min(1.0, (CMYK.z)+(CMYK.w)) );\n" \ 155 | " return cmy;\n" \ 156 | "}\n" 157 | inline glm::vec3 convertCMYK2RGB(glm::vec4 CMYK) 158 | { 159 | return glm::vec3(1 - glm::min(1.0f, (CMYK.x) + (CMYK.w)), 1 - glm::min(1.0f, (CMYK.y) + (CMYK.w)), 160 | 1 - glm::min(1.0f, (CMYK.z) + (CMYK.w))); 161 | } 162 | 163 | 164 | // sampling 2 textures and output RGBA 165 | static const char* g_glslf_Tex_CMYA_KA_2_RGBA = 166 | "#version 330\n" 167 | "#extension GL_ARB_separate_shader_objects : enable\n" 168 | "uniform vec4 CMYK_Mask;\n" 169 | "uniform sampler2D sampler_CMYA;\n" 170 | "uniform sampler2D sampler_KA;\n" 171 | "layout(location=0) in vec2 Tc;\n" 172 | "layout(location=0) out vec4 outColor;\n" CMYK2RGB 173 | "void main() {\n" 174 | " vec4 c = vec4(0);\n" 175 | " float alpha = 0;\n" 176 | " c = texelFetch(sampler_CMYA, ivec2(Tc), 0);\n" 177 | " alpha = c.w;\n" 178 | " c.w = texelFetch(sampler_KA, ivec2(Tc), 0).x;\n" 179 | " outColor = vec4(OneMinusCMYK2RGB(CMYK_Mask * (1-c)), alpha);\n" 180 | "}\n"; 181 | 182 | // for sampling MSAA Texture 183 | #define DEFINE_GLSLF_TEXMS_CMYA_KA_2_RGBA(VAR, msaa) \ 184 | static const char* VAR = \ 185 | "#version 330\n" \ 186 | "#extension GL_ARB_separate_shader_objects : enable\n" \ 187 | "uniform vec4 CMYK_Mask;\n" \ 188 | "uniform sampler2DMS samplerMS_CMYA;\n" \ 189 | "uniform sampler2DMS samplerMS_KA;\n" \ 190 | "layout(location=0) in vec2 Tc;\n" \ 191 | "layout(location=0) out vec4 outColor;\n" CMYK2RGB \ 192 | "void main() {\n" \ 193 | " vec4 c = vec4(0);\n" \ 194 | " float alpha = 0;\n" \ 195 | " for(int i=0; i<" #msaa \ 196 | "; i++) {\n" \ 197 | " vec4 tex;\n" \ 198 | " tex = texelFetch(samplerMS_CMYA, ivec2(Tc), i);\n" \ 199 | " alpha += tex.w;" \ 200 | " tex.w = texelFetch(samplerMS_KA, ivec2(Tc), i).x;\n" \ 201 | " c += tex;" \ 202 | " }\n" \ 203 | " outColor = vec4(OneMinusCMYK2RGB(CMYK_Mask * (1-(c / " #msaa "))), alpha/" #msaa \ 204 | ");\n" \ 205 | "}\n"; 206 | 207 | DEFINE_GLSLF_TEXMS_CMYA_KA_2_RGBA(g_glslf_TexMS_CMYA_KA_2_RGBA_2x, 2) 208 | DEFINE_GLSLF_TEXMS_CMYA_KA_2_RGBA(g_glslf_TexMS_CMYA_KA_2_RGBA_8x, 8) 209 | DEFINE_GLSLF_TEXMS_CMYA_KA_2_RGBA(g_glslf_TexMS_CMYA_KA_2_RGBA_16x, 16) 210 | static const char* g_glslf_TexMS_CMYA_KA_2_RGBA[3] = {g_glslf_TexMS_CMYA_KA_2_RGBA_2x, g_glslf_TexMS_CMYA_KA_2_RGBA_8x, 211 | g_glslf_TexMS_CMYA_KA_2_RGBA_16x}; 212 | 213 | // for sampling MSAA Texture 214 | #define DEFINE_GLSLF_IMAGEMS_CMYA_KA_2_RGBA(VAR, msaa) \ 215 | static const char* VAR = \ 216 | "#version 420\n" \ 217 | "uniform vec4 CMYK_Mask;\n" \ 218 | "uniform layout(rgba8) image2DMS imageMS_CMYA;\n" \ 219 | "uniform layout(rgba8) image2DMS imageMS_KA;\n" \ 220 | "layout(location=0) in vec2 Tc;\n" \ 221 | "layout(location=0) out vec4 outColor;\n" CMYK2RGB \ 222 | "void main() {\n" \ 223 | " vec4 c = vec4(0);\n" \ 224 | " float alpha = 0;\n" \ 225 | " for(int i=0; i<" #msaa \ 226 | "; i++) {\n" \ 227 | " vec4 tex;\n" \ 228 | " tex = imageLoad(imageMS_CMYA, ivec2(Tc), i);\n" \ 229 | " alpha += tex.w;" \ 230 | " tex.w = imageLoad(imageMS_KA, ivec2(Tc), i).x;\n" \ 231 | " c += tex;" \ 232 | " }\n" \ 233 | " outColor = vec4(OneMinusCMYK2RGB(CMYK_Mask * (1-(c / " #msaa "))), alpha/" #msaa \ 234 | ");\n" \ 235 | "}\n"; 236 | 237 | DEFINE_GLSLF_IMAGEMS_CMYA_KA_2_RGBA(g_glslf_ImageMS_CMYA_KA_2_RGBA_2x, 2) 238 | DEFINE_GLSLF_IMAGEMS_CMYA_KA_2_RGBA(g_glslf_ImageMS_CMYA_KA_2_RGBA_8x, 8) 239 | DEFINE_GLSLF_IMAGEMS_CMYA_KA_2_RGBA(g_glslf_ImageMS_CMYA_KA_2_RGBA_16x, 16) 240 | static const char* g_glslf_ImageMS_CMYA_KA_2_RGBA[3] = {g_glslf_ImageMS_CMYA_KA_2_RGBA_2x, g_glslf_ImageMS_CMYA_KA_2_RGBA_8x, 241 | g_glslf_ImageMS_CMYA_KA_2_RGBA_16x}; 242 | 243 | static GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, 244 | GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5, GL_COLOR_ATTACHMENT6}; 245 | 246 | //------------------------------------ 247 | // Blending Equations 248 | #define BLENDINGLIST() \ 249 | ENUMDECL(GL_FUNC_ADD) \ 250 | ENUMDECL(GL_SRC_NV) \ 251 | ENUMDECL(GL_DST_NV) \ 252 | ENUMDECL(GL_SRC_OVER_NV) \ 253 | ENUMDECL(GL_DST_OVER_NV) \ 254 | ENUMDECL(GL_SRC_IN_NV) \ 255 | ENUMDECL(GL_DST_IN_NV) \ 256 | ENUMDECL(GL_SRC_OUT_NV) \ 257 | ENUMDECL(GL_DST_OUT_NV) \ 258 | ENUMDECL(GL_SRC_ATOP_NV) \ 259 | ENUMDECL(GL_DST_ATOP_NV) \ 260 | /*ENUMDECL(GL_XOR_NV)*/ \ 261 | ENUMDECL(GL_MULTIPLY_NV) \ 262 | ENUMDECL(GL_SCREEN_NV) \ 263 | ENUMDECL(GL_OVERLAY_NV) \ 264 | ENUMDECL(GL_DARKEN_NV) \ 265 | ENUMDECL(GL_LIGHTEN_NV) \ 266 | ENUMDECL(GL_COLORDODGE_NV) \ 267 | ENUMDECL(GL_COLORBURN_NV) \ 268 | ENUMDECL(GL_HARDLIGHT_NV) \ 269 | ENUMDECL(GL_SOFTLIGHT_NV) \ 270 | ENUMDECL(GL_DIFFERENCE_NV) \ 271 | ENUMDECL(GL_EXCLUSION_NV) \ 272 | /*ENUMDECL(INVERT)*/ \ 273 | ENUMDECL(GL_INVERT_RGB_NV) \ 274 | ENUMDECL(GL_LINEARDODGE_NV) \ 275 | ENUMDECL(GL_LINEARBURN_NV) \ 276 | ENUMDECL(GL_VIVIDLIGHT_NV) \ 277 | ENUMDECL(GL_LINEARLIGHT_NV) \ 278 | ENUMDECL(GL_PINLIGHT_NV) \ 279 | ENUMDECL(GL_HARDMIX_NV) \ 280 | /*ENUMDECL(GL_HSL_HUE_NV) can only work with RGB*/ \ 281 | /*ENUMDECL(GL_HSL_SATURATION_NV) can only work with RGB*/ \ 282 | /*ENUMDECL(GL_HSL_COLOR_NV) can only work with RGB*/ \ 283 | /*ENUMDECL(GL_HSL_LUMINOSITY_NV) can only work with RGB*/ \ 284 | ENUMDECL(GL_PLUS_NV) \ 285 | ENUMDECL(GL_PLUS_CLAMPED_NV) \ 286 | ENUMDECL(GL_PLUS_CLAMPED_ALPHA_NV) \ 287 | ENUMDECL(GL_PLUS_DARKER_NV) \ 288 | ENUMDECL(GL_MINUS_NV) \ 289 | ENUMDECL(GL_MINUS_CLAMPED_NV) \ 290 | ENUMDECL(GL_CONTRAST_NV) \ 291 | ENUMDECL(GL_INVERT_OVG_NV) \ 292 | /*ENUMDECL(GL_RED_NV)*/ \ 293 | /*ENUMDECL(GL_GREEN_NV)*/ \ 294 | /*ENUMDECL(GL_BLUE_NV)*/ \ 295 | ENUMDECL(GL_ZERO) 296 | 297 | #define ENUMDECL(a) #a, 298 | const char* blendequationNames[] = {BLENDINGLIST()}; 299 | #undef ENUMDECL 300 | #define ENUMDECL(a) a, 301 | GLenum blendequations[] = {BLENDINGLIST()}; 302 | int g_curBlendEquation = 0; 303 | 304 | //------------------------------------ 305 | // Blend funcs 306 | #define BLENDINGFUNCS() \ 307 | ENUMDECL(GL_ONE) \ 308 | ENUMDECL(GL_SRC_COLOR) \ 309 | ENUMDECL(GL_ONE_MINUS_SRC_COLOR) \ 310 | ENUMDECL(GL_DST_COLOR) \ 311 | ENUMDECL(GL_ONE_MINUS_DST_COLOR) \ 312 | ENUMDECL(GL_SRC_ALPHA) \ 313 | ENUMDECL(GL_ONE_MINUS_SRC_ALPHA) \ 314 | ENUMDECL(GL_DST_ALPHA) \ 315 | ENUMDECL(GL_ONE_MINUS_DST_ALPHA) \ 316 | ENUMDECL(GL_CONSTANT_COLOR) \ 317 | ENUMDECL(GL_ONE_MINUS_CONSTANT_COLOR) \ 318 | ENUMDECL(GL_CONSTANT_ALPHA) \ 319 | ENUMDECL(GL_ONE_MINUS_CONSTANT_ALPHA) \ 320 | ENUMDECL(GL_ZERO) 321 | 322 | #undef ENUMDECL 323 | #define ENUMDECL(a) #a, 324 | const char* blendfuncNames[] = {BLENDINGFUNCS()}; 325 | #undef ENUMDECL 326 | #define ENUMDECL(a) a, 327 | GLenum blendfuncs[] = {BLENDINGFUNCS()}; 328 | 329 | int g_blendSRC = 5; 330 | int g_blendDST = 6; 331 | //------------------------------------ 332 | // used to give a string name to the class through constructor: helps for error checking 333 | #define P(p) p(#p) 334 | 335 | GLSLProgram P(g_prog_Cst_OneMinusCMYK_A); 336 | GLSLProgram P(g_progPR_Cst_OneMinusCMYK_A); 337 | GLSLProgram P(g_prog_Cst_RGBA); 338 | GLSLProgram P(g_progPR_Cst_RGBA); 339 | 340 | GLSLProgram P(g_progTexCMYA_KA_2_RGBA); 341 | GLSLProgram g_progTexMS_CMYA_KA_2_RGBA[3]; 342 | GLSLProgram P(g_progTex_CMYA_KA_2_RGBA); 343 | GLSLProgram g_progImageMS_CMYA_KA_2_RGBA[3]; 344 | 345 | GLuint g_vboCircle = 0; 346 | GLuint g_vboQuad = 0; 347 | float g_alpha = 0.5; 348 | int g_NObjs = 6; 349 | bool g_usePathObj = true; 350 | bool g_activeC = true; 351 | bool g_activeM = true; 352 | bool g_activeY = true; 353 | bool g_activeK = true; 354 | bool g_blendEnable = true; 355 | int g_MSAARaster = 8; 356 | int g_MSAAVal[] = {1, 2, 8, 16}; 357 | int g_CurMSAAColor = 0; 358 | bool g_has_GL_NV_framebuffer_mixed_samples = false; 359 | bool g_buseUI = true; 360 | 361 | 362 | unsigned int g_pathObj = 0; 363 | 364 | // From the driver, renderbuffers are really useless: they are just textures that cannot be used as textures 365 | // it is now advised to just use textures and avoid renderbuffers... 366 | //#define USE_RENDERBUFFERS 367 | 368 | // FBO Stuff 369 | GLuint fboSz[2] = {0, 0}; 370 | namespace Texture { 371 | GLuint CMYA; 372 | GLuint KA; 373 | GLuint MS_CMYA; 374 | GLuint MS_KA; 375 | #ifndef USE_RENDERBUFFERS 376 | GLuint DST; 377 | GLuint MS_DST; 378 | #endif 379 | }; // namespace Texture 380 | 381 | #ifdef USE_RENDERBUFFERS 382 | namespace Renderbuffer { 383 | GLuint RGBA; 384 | GLuint RGBAMS; 385 | GLuint DST; 386 | GLuint DSTMS; 387 | }; // namespace Renderbuffer 388 | #endif 389 | 390 | namespace FBO { 391 | GLuint TexMS_CMYA_KA_DST; 392 | GLuint Tex_CMYA_KA; 393 | GLuint TexMS_CMYA; 394 | GLuint Tex_CMYA; 395 | GLuint TexMS_KA; 396 | GLuint Tex_KA; 397 | #ifdef USE_RENDERBUFFERS 398 | GLuint RbMS; 399 | GLuint Rb; 400 | #endif 401 | }; // namespace FBO 402 | #define TexMS_RGBA TexMS_CMYA // we can recycle the CMYA for RGBA 403 | 404 | enum BlitMode 405 | { 406 | RESOLVEWITHBLIT = 0, 407 | RESOLVEWITHSHADERTEX, 408 | RESOLVEWITHSHADERIMAGE, 409 | RESOLVERGBATOBACKBUFFER, // for the RGBA case 410 | }; 411 | BlitMode blitMode; 412 | 413 | enum MRTMode 414 | { 415 | RENDER1STEP = 0, 416 | RENDER2STEPS, 417 | RENDER1STEPRGBA, 418 | }; 419 | MRTMode mrtMode = RENDER1STEP; 420 | 421 | GLuint g_vao = 0; 422 | 423 | //------------------------------------------------------------------------------ 424 | // It is possible that this callback is invoked from another thread 425 | // so let's just append messages for later diplay in the main loop 426 | //------------------------------------------------------------------------------ 427 | struct LogMessage 428 | { 429 | LogMessage(int l, const char* t) 430 | { 431 | level = l; 432 | txt = t; 433 | } 434 | int level; 435 | std::string txt; 436 | }; 437 | typedef std::list Messages; 438 | //------------------------------------------------------------------------------ 439 | void sample_print(int level, const char* txt) {} 440 | 441 | //------------------------------------------------------------------------------ 442 | //------------------------------------------------------------------------------ 443 | // UI stuff 444 | //------------------------------------------------------------------------------ 445 | //------------------------------------------------------------------------------ 446 | 447 | #define COMBO_BLITMODE 0 448 | #define COMBO_MRTMODE 1 449 | #define COMBO_MSAACOL 2 450 | #define COMBO_MSAARAST 3 451 | #define COMBO_BLENDEQ 4 452 | #define COMBO_BLENDFNSRC 5 453 | #define COMBO_BLENDFNDST 6 454 | void MyWindow::processUI(int width, int height, double dt) 455 | { 456 | // Update imgui configuration 457 | auto& imgui_io = ImGui::GetIO(); 458 | imgui_io.DeltaTime = static_cast(dt); 459 | imgui_io.DisplaySize = ImVec2(width, height); 460 | 461 | ImGui::NewFrame(); 462 | ImGui::SetNextWindowBgAlpha(0.5); 463 | ImGui::SetNextWindowSize(ImGuiH::dpiScaled(450, 0), ImGuiCond_FirstUseEver); 464 | if(ImGui::Begin("NVIDIA " PROJECT_NAME, nullptr)) 465 | { 466 | //ImGui::PushItemWidth(200); 467 | ImGui::Text("gl and vk version"); 468 | ImGuiH::InputIntClamped("N Objs x&y", &g_NObjs, 1, 100); 469 | ImGui::Separator(); 470 | // 471 | // Blit modes 472 | // 473 | m_guiRegistry.enumCombobox(COMBO_BLITMODE, "Blit Mode", &blitMode); 474 | // 475 | // render mode on Muyltiple render-targets 476 | // 477 | m_guiRegistry.enumCombobox(COMBO_MRTMODE, "Render Pass", &mrtMode); 478 | // 479 | // Color samples combo 480 | // 481 | m_guiRegistry.enumCombobox(COMBO_MSAACOL, "MSAA Color samples", &g_CurMSAAColor); 482 | // 483 | // Mixed samples combo 484 | // 485 | if(g_has_GL_NV_framebuffer_mixed_samples) 486 | { 487 | m_guiRegistry.enumCombobox(COMBO_MSAARAST, "MSAA Raster samples", &g_MSAARaster); 488 | } 489 | // 490 | // Blending Equations 491 | // 492 | m_guiRegistry.enumCombobox(COMBO_BLENDEQ, "Blend Equation", &g_curBlendEquation); 493 | // 494 | // Blending Funcs 495 | // 496 | m_guiRegistry.enumCombobox(COMBO_BLENDFNSRC, "Blend Func SRC", &g_blendSRC); 497 | m_guiRegistry.enumCombobox(COMBO_BLENDFNDST, "Blend Func DST", &g_blendDST); 498 | // 499 | // Global transparency 500 | // 501 | ImGui::Separator(); 502 | ImGuiH::InputFloatClamped("Global Alpha", &g_alpha, 0.0, 1.0); 503 | //ImGui::Checkbox("continuous render", &m_realtime.bNonStopRendering); 504 | ImGui::Checkbox("animation", &s_bCameraAnim); 505 | ImGui::Separator(); 506 | ImGui::Text("('h' to toggle help)"); 507 | //if(s_bStats) 508 | // h += m_oglTextBig.drawString(5, m_winSz[1]-h, hudStats.c_str(), 0, glm::vec4(0.8,0.8,1.0,0.5).vec_array); 509 | 510 | if(s_helpText) 511 | { 512 | ImGui::BeginChild("Help", ImVec2(400, 110), true); 513 | // camera help 514 | //ImGui::SetNextWindowCollapsed(0); 515 | const char* txt = getHelpText(); 516 | ImGui::Text("'`' or 'u' to toggle UI\n"); 517 | ImGui::Text("%s", txt); 518 | ImGui::EndChild(); 519 | } 520 | 521 | int avg = 100; 522 | 523 | if(s_profiler.getTotalFrames() % avg == avg - 1) 524 | { 525 | s_profiler.getAveragedValues("frame", s_statsCpuTime, s_statsGpuTime); 526 | } 527 | 528 | float gpuTimeF = float(s_statsGpuTime); 529 | float cpuTimeF = float(s_statsCpuTime); 530 | float maxTimeF = std::max(std::max(cpuTimeF, gpuTimeF), 0.0001f); 531 | 532 | ImGui::Text("Frame [ms]: %2.1f", dt * 1000.0f); 533 | ImGui::Text("Scene GPU [ms]: %2.3f", gpuTimeF / 1000.0f); 534 | ImGui::Text("Scene CPU [ms]: %2.3f", cpuTimeF / 1000.0f); 535 | ImGui::ProgressBar(gpuTimeF / maxTimeF, ImVec2(0.0f, 0.0f)); 536 | ImGui::ProgressBar(cpuTimeF / maxTimeF, ImVec2(0.0f, 0.0f)); 537 | } 538 | ImGui::End(); 539 | } 540 | 541 | //------------------------------------------------------------------------------ 542 | //------------------------------------------------------------------------------ 543 | // FBO stuff 544 | //------------------------------------------------------------------------------ 545 | //------------------------------------------------------------------------------ 546 | 547 | bool CheckFramebufferStatus() 548 | { 549 | GLenum status; 550 | status = (GLenum)glCheckFramebufferStatus(GL_FRAMEBUFFER); 551 | switch(status) 552 | { 553 | case GL_FRAMEBUFFER_COMPLETE: 554 | return true; 555 | case GL_FRAMEBUFFER_UNSUPPORTED: 556 | LOGE("Unsupported framebuffer format\n"); 557 | assert(!"Unsupported framebuffer format"); 558 | break; 559 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 560 | LOGE("Framebuffer incomplete, missing attachment\n"); 561 | assert(!"Framebuffer incomplete, missing attachment"); 562 | break; 563 | //case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 564 | // PRINTF(("Framebuffer incomplete, attached images must have same dimensions\n")); 565 | // assert(!"Framebuffer incomplete, attached images must have same dimensions"); 566 | // break; 567 | //case GL_FRAMEBUFFER_INCOMPLETE_FORMATS: 568 | // PRINTF(("Framebuffer incomplete, attached images must have same format\n")); 569 | // assert(!"Framebuffer incomplete, attached images must have same format"); 570 | // break; 571 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: 572 | LOGE("Framebuffer incomplete, missing draw buffer\n"); 573 | assert(!"Framebuffer incomplete, missing draw buffer"); 574 | break; 575 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: 576 | LOGE("Framebuffer incomplete, missing read buffer\n"); 577 | assert(!"Framebuffer incomplete, missing read buffer"); 578 | break; 579 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 580 | LOGE("Framebuffer incomplete attachment\n"); 581 | assert(!"Framebuffer incomplete attachment"); 582 | break; 583 | case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: 584 | LOGE("Framebuffer incomplete multisample\n"); 585 | assert(!"Framebuffer incomplete multisample"); 586 | break; 587 | default: 588 | LOGE("Error %x\n", status); 589 | assert(!"unknown FBO Error"); 590 | break; 591 | } 592 | return false; 593 | } 594 | 595 | //------------------------------------------------------------------------------ 596 | // 597 | //------------------------------------------------------------------------------ 598 | GLuint createTexture(int w, int h, int samples, int coverageSamples, GLenum intfmt, GLenum fmt) 599 | { 600 | GLuint textureID; 601 | glGenTextures(1, &textureID); 602 | if(samples <= 1) 603 | { 604 | glBindTexture(GL_TEXTURE_2D, textureID); 605 | glTexImage2D(GL_TEXTURE_2D, 0, intfmt, w, h, 0, GL_RGBA, GL_FLOAT, NULL); 606 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 607 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 608 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 609 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 610 | } 611 | else 612 | { 613 | glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureID); 614 | // Note: fixed-samples set to GL_TRUE, otherwise it could fail when attaching to FBO having render-buffer !! 615 | if(coverageSamples > 1) 616 | { 617 | glTexImage2DMultisampleCoverageNV(GL_TEXTURE_2D_MULTISAMPLE, coverageSamples, samples, intfmt, w, h, GL_TRUE); 618 | } 619 | else 620 | { 621 | glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, intfmt, w, h, GL_TRUE); 622 | } 623 | // Multi-sample textures don't suupport sampler state settings 624 | //glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 625 | //glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 626 | //glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 627 | //glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 628 | } 629 | return textureID; 630 | } 631 | //------------------------------------------------------------------------------ 632 | // 633 | //------------------------------------------------------------------------------ 634 | GLuint createTextureRGBA8(int w, int h, int samples, int coverageSamples) 635 | { 636 | return createTexture(w, h, samples, coverageSamples, GL_RGBA8, GL_RGBA); 637 | } 638 | 639 | //------------------------------------------------------------------------------ 640 | // 641 | //------------------------------------------------------------------------------ 642 | GLuint createTextureDST(int w, int h, int samples, int coverageSamples) 643 | { 644 | //return createTexture(w, h, samples, coverageSamples, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8); 645 | return createTexture(w, h, samples, coverageSamples, GL_STENCIL_INDEX8, GL_STENCIL_INDEX8); 646 | } 647 | 648 | //------------------------------------------------------------------------------ 649 | // 650 | //------------------------------------------------------------------------------ 651 | #ifdef USE_RENDERBUFFERS 652 | GLuint createRenderBuffer(int w, int h, int samples, int coverageSamples, GLenum fmt) 653 | { 654 | int query; 655 | GLuint rb; 656 | glGenRenderbuffers(1, &rb); 657 | glBindRenderbuffer(GL_RENDERBUFFER, rb); 658 | if(coverageSamples) 659 | { 660 | glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, coverageSamples, samples, fmt, w, h); 661 | glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &query); 662 | if(query < coverageSamples) 663 | rb = 0; 664 | else if(query > coverageSamples) 665 | { 666 | // report back the actual number 667 | coverageSamples = query; 668 | LOGW("Warning: coverage samples is now %d\n", coverageSamples); 669 | } 670 | glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &query); 671 | if(query < samples) 672 | rb = 0; 673 | else if(query > samples) 674 | { 675 | // report back the actual number 676 | samples = query; 677 | LOGW("Warning: depth-samples is now %d\n", samples); 678 | } 679 | } 680 | else 681 | { 682 | // create a regular MSAA color buffer 683 | glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, fmt, w, h); 684 | // check the number of samples 685 | glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &query); 686 | 687 | if(query < samples) 688 | rb = 0; 689 | else if(query > samples) 690 | { 691 | samples = query; 692 | LOGW("Warning: depth-samples is now %d\n", samples); 693 | } 694 | } 695 | glBindRenderbuffer(GL_RENDERBUFFER, 0); 696 | return rb; 697 | } 698 | 699 | //------------------------------------------------------------------------------ 700 | // 701 | //------------------------------------------------------------------------------ 702 | GLuint createRenderBufferRGBA8(int w, int h, int samples, int coverageSamples) 703 | { 704 | return createRenderBuffer(w, h, samples, coverageSamples, GL_RGBA8); 705 | } 706 | 707 | //------------------------------------------------------------------------------ 708 | // 709 | //------------------------------------------------------------------------------ 710 | GLuint createRenderBufferD24S8(int w, int h, int samples, int coverageSamples) 711 | { 712 | return createRenderBuffer(w, h, samples, coverageSamples, GL_DEPTH24_STENCIL8); 713 | } 714 | //------------------------------------------------------------------------------ 715 | // 716 | //------------------------------------------------------------------------------ 717 | GLuint createRenderBufferS8(int w, int h, int samples, int coverageSamples) 718 | { 719 | return createRenderBuffer(w, h, samples, coverageSamples, GL_STENCIL_INDEX8); 720 | } 721 | #endif 722 | //------------------------------------------------------------------------------ 723 | // 724 | //------------------------------------------------------------------------------ 725 | GLuint createFBO() 726 | { 727 | GLuint fb; 728 | glGenFramebuffers(1, &fb); 729 | return fb; 730 | } 731 | 732 | //------------------------------------------------------------------------------ 733 | // 734 | //------------------------------------------------------------------------------ 735 | bool attachTexture2D(GLuint framebuffer, GLuint textureID, int colorAttachment) 736 | { 737 | glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 738 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttachment, GL_TEXTURE_2D, textureID, 0); 739 | return CheckFramebufferStatus(); 740 | } 741 | 742 | //------------------------------------------------------------------------------ 743 | // 744 | //------------------------------------------------------------------------------ 745 | bool attachTexture2DMS(GLuint framebuffer, GLuint textureID, int colorAttachment) 746 | { 747 | if(g_MSAAVal[g_CurMSAAColor] <= 1) 748 | return attachTexture2D(framebuffer, textureID, colorAttachment); 749 | glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 750 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttachment, GL_TEXTURE_2D_MULTISAMPLE, textureID, 0); 751 | return CheckFramebufferStatus(); 752 | } 753 | 754 | //------------------------------------------------------------------------------ 755 | // 756 | //------------------------------------------------------------------------------ 757 | #ifdef USE_RENDERBUFFERS 758 | bool attachRenderbuffer(GLuint framebuffer, GLuint rb, int colorAttachment) 759 | { 760 | glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 761 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttachment, GL_RENDERBUFFER, rb); 762 | return CheckFramebufferStatus(); 763 | } 764 | //------------------------------------------------------------------------------ 765 | // 766 | //------------------------------------------------------------------------------ 767 | bool attachDSTRenderbuffer(GLuint framebuffer, GLuint dstrb) 768 | { 769 | bool bRes; 770 | glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 771 | //glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, dstrb); 772 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, dstrb); 773 | return CheckFramebufferStatus(); 774 | } 775 | #endif 776 | //------------------------------------------------------------------------------ 777 | // 778 | //------------------------------------------------------------------------------ 779 | bool attachDSTTexture2D(GLuint framebuffer, GLuint textureDepthID, GLenum target = GL_TEXTURE_2D) 780 | { 781 | bool bRes; 782 | glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 783 | //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, textureDepthID, 0); 784 | //bRes = CheckFramebufferStatus(); 785 | //if(!bRes) return false; 786 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, target, textureDepthID, 0); 787 | bRes = CheckFramebufferStatus(); 788 | return bRes; 789 | } 790 | 791 | //------------------------------------------------------------------------------ 792 | // 793 | //------------------------------------------------------------------------------ 794 | bool attachDSTTexture2DMS(GLuint framebuffer, GLuint textureDepthID) 795 | { 796 | return attachDSTTexture2D(framebuffer, textureDepthID, (g_MSAARaster > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D); 797 | } 798 | 799 | //------------------------------------------------------------------------------ 800 | // 801 | //------------------------------------------------------------------------------ 802 | void deleteTexture(GLuint texture) 803 | { 804 | glDeleteTextures(1, &texture); 805 | } 806 | 807 | //------------------------------------------------------------------------------ 808 | // 809 | //------------------------------------------------------------------------------ 810 | #ifdef USE_RENDERBUFFERS 811 | void deleteRenderBuffer(GLuint rb) 812 | { 813 | glDeleteRenderbuffers(1, &rb); 814 | } 815 | #endif 816 | //------------------------------------------------------------------------------ 817 | // 818 | //------------------------------------------------------------------------------ 819 | void deleteFBO(GLuint fbo) 820 | { 821 | glDeleteFramebuffers(1, &fbo); 822 | } 823 | 824 | //------------------------------------------------------------------------------ 825 | // 826 | //------------------------------------------------------------------------------ 827 | void blitFBO(GLuint srcFBO, GLuint dstFBO, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLenum filtering) 828 | { 829 | glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFBO); 830 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFBO); 831 | // GL_NEAREST is needed when Stencil/depth are involved 832 | glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, 833 | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, filtering); 834 | glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 835 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 836 | } 837 | //------------------------------------------------------------------------------ 838 | // 839 | //------------------------------------------------------------------------------ 840 | void blitFBONearest(GLuint srcFBO, GLuint dstFBO, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) 841 | { 842 | blitFBO(srcFBO, dstFBO, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_NEAREST); 843 | } 844 | //------------------------------------------------------------------------------ 845 | // 846 | //------------------------------------------------------------------------------ 847 | void blitFBOLinear(GLuint srcFBO, GLuint dstFBO, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) 848 | { 849 | blitFBO(srcFBO, dstFBO, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_LINEAR); 850 | } 851 | 852 | //------------------------------------------------------------------------------ 853 | // 854 | //------------------------------------------------------------------------------ 855 | void deleteRenderTargets() 856 | { 857 | if(FBO::TexMS_CMYA_KA_DST) 858 | deleteFBO(FBO::TexMS_CMYA_KA_DST); 859 | if(FBO::Tex_CMYA_KA) 860 | deleteFBO(FBO::Tex_CMYA_KA); 861 | if(FBO::TexMS_CMYA) 862 | deleteFBO(FBO::TexMS_CMYA); 863 | if(FBO::Tex_CMYA) 864 | deleteFBO(FBO::Tex_CMYA); 865 | if(FBO::TexMS_KA) 866 | deleteFBO(FBO::TexMS_KA); 867 | if(FBO::Tex_KA) 868 | deleteFBO(FBO::Tex_KA); 869 | #ifdef USE_RENDERBUFFERS 870 | if(FBO::RbMS) 871 | deleteFBO(FBO::RbMS); 872 | if(FBO::Rb) 873 | deleteFBO(FBO::Rb); 874 | #endif 875 | if(Texture::CMYA) 876 | deleteTexture(Texture::CMYA); 877 | if(Texture::KA) 878 | deleteTexture(Texture::KA); 879 | if(Texture::MS_CMYA) 880 | deleteTexture(Texture::MS_CMYA); 881 | if(Texture::MS_KA) 882 | deleteTexture(Texture::MS_KA); 883 | #ifndef USE_RENDERBUFFERS 884 | if(Texture::MS_DST) 885 | deleteTexture(Texture::MS_DST); 886 | if(Texture::DST) 887 | deleteTexture(Texture::DST); 888 | #else 889 | if(Renderbuffer::RGBA) 890 | deleteRenderBuffer(Renderbuffer::RGBA); 891 | if(Renderbuffer::RGBAMS) 892 | deleteRenderBuffer(Renderbuffer::RGBAMS); 893 | if(Renderbuffer::DST) 894 | deleteRenderBuffer(Renderbuffer::DST); 895 | if(Renderbuffer::DSTMS) 896 | deleteRenderBuffer(Renderbuffer::DSTMS); 897 | #endif 898 | fboSz[0] = 0; 899 | fboSz[1] = 0; 900 | } 901 | 902 | //------------------------------------------------------------------------------ 903 | // 904 | //------------------------------------------------------------------------------ 905 | void buildRenderTargets(int w, int h) 906 | { 907 | deleteRenderTargets(); 908 | if(g_has_GL_NV_framebuffer_mixed_samples) 909 | { 910 | if(g_MSAARaster < g_MSAAVal[g_CurMSAAColor]) 911 | g_MSAARaster = g_MSAAVal[g_CurMSAAColor]; 912 | } 913 | else 914 | g_MSAARaster = g_MSAAVal[g_CurMSAAColor]; 915 | 916 | LOGI("Building Render targets with MSAA Color = %d and MSAA Raster = %d\n", g_MSAAVal[g_CurMSAAColor], g_MSAARaster); 917 | fboSz[0] = w; 918 | fboSz[1] = h; 919 | // a texture 920 | Texture::CMYA = createTextureRGBA8(w, h, 0, 0); 921 | Texture::KA = createTextureRGBA8(w, h, 0, 0); 922 | // a texture in MSAA 923 | Texture::MS_CMYA = createTextureRGBA8(w, h, g_MSAAVal[g_CurMSAAColor], 0); 924 | Texture::MS_KA = createTextureRGBA8(w, h, g_MSAAVal[g_CurMSAAColor], 0); // TODO: RA8 925 | #ifndef USE_RENDERBUFFERS 926 | Texture::DST = createTextureDST(w, h, 0, 0); 927 | Texture::MS_DST = createTextureDST(w, h, g_MSAARaster, 0); 928 | #else 929 | // a renderbuffer 930 | Renderbuffer::RGBA = createRenderBufferRGBA8(w, h, 0, 0); 931 | // a renderbuffer in MSAA 932 | Renderbuffer::RGBAMS = createRenderBufferRGBA8(w, h, g_MSAAVal[g_CurMSAAColor], 0); 933 | // a depth stencil 934 | Renderbuffer::DST = createRenderBufferS8 /*D24S8*/ (w, h, 0, 0); 935 | // a depth stencil in MSAA 936 | Renderbuffer::DSTMS = createRenderBufferS8 /*D24S8*/ (w, h, g_MSAARaster, 0); 937 | #endif 938 | // fbo for texture MSAA as the color buffer 939 | FBO::TexMS_CMYA_KA_DST = createFBO(); 940 | { 941 | #ifdef USE_RENDERBUFFERS 942 | attachDSTRenderbuffer(FBO::TexMS_CMYA_KA_DST, Renderbuffer::DSTMS); 943 | #else 944 | attachDSTTexture2DMS(FBO::TexMS_CMYA_KA_DST, Texture::MS_DST); 945 | #endif 946 | attachTexture2DMS(FBO::TexMS_CMYA_KA_DST, Texture::MS_CMYA, 0); 947 | attachTexture2DMS(FBO::TexMS_CMYA_KA_DST, Texture::MS_KA, 1); 948 | } 949 | // fbo for a texture as the color buffer 950 | 951 | FBO::Tex_CMYA_KA = createFBO(); 952 | { 953 | attachTexture2D(FBO::Tex_CMYA_KA, Texture::CMYA, 0); 954 | attachTexture2D(FBO::Tex_CMYA_KA, Texture::KA, 1); 955 | } 956 | // fbo for Blit operation 957 | FBO::Tex_CMYA = createFBO(); 958 | { 959 | attachTexture2D(FBO::Tex_CMYA, Texture::CMYA, 0); 960 | } 961 | FBO::Tex_KA = createFBO(); 962 | { 963 | attachTexture2D(FBO::Tex_KA, Texture::KA, 0); 964 | } 965 | FBO::TexMS_CMYA = createFBO(); 966 | { 967 | attachTexture2DMS(FBO::TexMS_CMYA, Texture::MS_CMYA, 0); 968 | } 969 | FBO::TexMS_KA = createFBO(); 970 | { 971 | attachTexture2DMS(FBO::TexMS_KA, Texture::MS_KA, 0); 972 | } 973 | // fbo for renderbuffer MSAA as the color buffer 974 | #ifdef USE_RENDERBUFFERS 975 | FBO::RbMS = createFBO(); 976 | { 977 | attachRenderbuffer(FBO::RbMS, Renderbuffer::RGBAMS, 0); 978 | //attachDSTRenderbuffer(FBO::RbMS, Renderbuffer::DSTMS); 979 | } 980 | // fbo for renderbuffer as the color buffer 981 | FBO::Rb = createFBO(); 982 | { 983 | attachRenderbuffer(FBO::Rb, Renderbuffer::RGBA, 0); 984 | attachDSTRenderbuffer(FBO::Rb, Renderbuffer::DST); 985 | } 986 | #endif 987 | // build a VBO for the size of the FBO 988 | // 989 | // make a VBO for Quad 990 | // 991 | if(g_vboQuad == 0) 992 | glGenBuffers(1, &g_vboQuad); 993 | glBindBuffer(GL_ARRAY_BUFFER, g_vboQuad); 994 | int vertices[2 * 4] = {0, 0, w, 0, 0, h, w, h}; 995 | glBufferData(GL_ARRAY_BUFFER, sizeof(int) * 2 * 4, vertices, GL_STATIC_DRAW); 996 | glBindBuffer(GL_ARRAY_BUFFER, 0); 997 | } 998 | //------------------------------------------------------------------------------ 999 | // 1000 | //------------------------------------------------------------------------------ 1001 | bool MyWindow::open(int posX, int posY, int width, int height, const char* title, const nvgl::ContextWindowCreateInfo& context) 1002 | { 1003 | if(!AppWindowCameraInertia::open(posX, posY, width, height, title, true)) 1004 | return false; 1005 | m_contextWindowGL.init(&context, m_internal, title); 1006 | ImGui::InitGL(); 1007 | s_profiler.init(); 1008 | 1009 | 1010 | m_camera.curEyePos = m_camera.eyePos = glm::vec3(0, 0, 3.0f); 1011 | LOGI("'1': Blit used for MSAA resolve"); 1012 | LOGI("'2': TexelFetch used on MSAA Texture to resolve"); 1013 | LOGI("'3': ImageLoad used on MSAA Texture to resolve"); 1014 | // 1015 | // UI 1016 | // 1017 | auto& imgui_io = ImGui::GetIO(); 1018 | imgui_io.IniFilename = nullptr; 1019 | m_guiRegistry.enumAdd(COMBO_BLITMODE, RESOLVEWITHBLIT, "Resolve with Blit"); 1020 | m_guiRegistry.enumAdd(COMBO_BLITMODE, RESOLVEWITHSHADERTEX, "Resolve with Shader&Texture Fetch"); 1021 | m_guiRegistry.enumAdd(COMBO_BLITMODE, RESOLVEWITHSHADERIMAGE, "Resolve with Shader&Image Load"); 1022 | m_guiRegistry.enumAdd(COMBO_BLITMODE, RESOLVERGBATOBACKBUFFER, "Resolve with blit : RGBA to backbuffer"); 1023 | m_guiRegistry.enumAdd(COMBO_MRTMODE, RENDER1STEP, "Render CMYA & KA to 2 RTs at a time"); 1024 | m_guiRegistry.enumAdd(COMBO_MRTMODE, RENDER2STEPS, "Render CMYA to RT#0 then KA to RT#1"); 1025 | m_guiRegistry.enumAdd(COMBO_MRTMODE, RENDER1STEPRGBA, "Render RGBA to RT#0 only"); 1026 | m_guiRegistry.enumAdd(COMBO_MSAACOL, 0, "MSAA OFF"); 1027 | m_guiRegistry.enumAdd(COMBO_MSAACOL, 1, "MSAA 2x"); 1028 | m_guiRegistry.enumAdd(COMBO_MSAACOL, 2, "MSAA 8x"); 1029 | 1030 | // TODO check "GL_NV_framebuffer_mixed_samples") 1031 | { 1032 | g_has_GL_NV_framebuffer_mixed_samples = true; 1033 | m_guiRegistry.enumAdd(COMBO_MSAARAST, 2, "MSAA 2x"); 1034 | m_guiRegistry.enumAdd(COMBO_MSAARAST, 4, "MSAA 4x"); 1035 | m_guiRegistry.enumAdd(COMBO_MSAARAST, 8, "MSAA 8x"); 1036 | m_guiRegistry.enumAdd(COMBO_MSAARAST, 16, "MSAA 16x"); 1037 | } 1038 | for(int be = 0; blendequations[be] != GL_ZERO; be++) 1039 | { 1040 | m_guiRegistry.enumAdd(COMBO_BLENDEQ, be, blendequationNames[be]); 1041 | } 1042 | for(int be = 0; blendfuncs[be] != GL_ZERO; be++) 1043 | { 1044 | m_guiRegistry.enumAdd(COMBO_BLENDFNSRC, be, blendfuncNames[be]); 1045 | } 1046 | for(int be = 0; blendfuncs[be] != GL_ZERO; be++) 1047 | { 1048 | m_guiRegistry.enumAdd(COMBO_BLENDFNDST, be, blendfuncNames[be]); 1049 | } 1050 | 1051 | m_realtime.bNonStopRendering = true; 1052 | // 1053 | // Shader Programs for rasterization 1054 | // 1055 | if(!g_prog_Cst_OneMinusCMYK_A.compileProgram(g_glslv_WVP_Position, NULL, g_glslf_OneMinusCMYK_A)) 1056 | return false; 1057 | if(!g_progPR_Cst_OneMinusCMYK_A.compileProgram(NULL, NULL, g_glslf_OneMinusCMYK_A)) 1058 | return false; 1059 | if(!g_prog_Cst_RGBA.compileProgram(g_glslv_WVP_Position, NULL, g_glslf_RGBA)) 1060 | return false; 1061 | if(!g_progPR_Cst_RGBA.compileProgram(NULL, NULL, g_glslf_RGBA)) 1062 | return false; 1063 | // 1064 | // Shader Programs for fullscreen processing 1065 | // 1066 | for(int i = 0; i < 3; i++) 1067 | { 1068 | if(!g_progTexMS_CMYA_KA_2_RGBA[i].compileProgram(g_glslv_Tc, NULL, g_glslf_TexMS_CMYA_KA_2_RGBA[i])) 1069 | return false; 1070 | if(!g_progImageMS_CMYA_KA_2_RGBA[i].compileProgram(g_glslv_Tc, NULL, g_glslf_ImageMS_CMYA_KA_2_RGBA[i])) 1071 | return false; 1072 | } 1073 | if(!g_progTex_CMYA_KA_2_RGBA.compileProgram(g_glslv_Tc, NULL, g_glslf_Tex_CMYA_KA_2_RGBA)) 1074 | return false; 1075 | // 1076 | // Misc OGL setup 1077 | // 1078 | glClearColor(0.0f, 0.1f, 0.1f, 1.0f); 1079 | glGenVertexArrays(1, &g_vao); 1080 | glBindVertexArray(g_vao); 1081 | // 1082 | // Circle 1083 | // 1084 | glGenBuffers(1, &g_vboCircle); 1085 | glBindBuffer(GL_ARRAY_BUFFER, g_vboCircle); 1086 | #define SUBDIVS 180 1087 | #define CIRCLESZ 0.5f 1088 | glm::vec3* data = new glm::vec3[SUBDIVS + 2]; 1089 | if(!data) 1090 | return false; 1091 | glm::vec3* p = data; 1092 | int j = 0; 1093 | *(p++) = glm::vec3(0, 0, 0); 1094 | for(int i = 0; i < SUBDIVS + 1; i++) 1095 | { 1096 | float a = glm::radians((float)i * (360.0f / (float)SUBDIVS)); 1097 | glm::vec3 v(CIRCLESZ * cosf(a), CIRCLESZ * sinf(a), 0.0f); 1098 | *(p++) = v; 1099 | } 1100 | glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * (SUBDIVS + 2), glm::value_ptr(data[0]), GL_STATIC_DRAW); 1101 | glBindBuffer(GL_ARRAY_BUFFER, 0); 1102 | delete[] data; 1103 | // 1104 | // NV-Path rendering 1105 | // 1106 | // TODO check GL_NV_path_rendering 1107 | { 1108 | g_usePathObj = true; 1109 | g_pathObj = glGenPathsNV(1); 1110 | static const GLubyte pathCommands[10] = { 1111 | GL_MOVE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, 1112 | GL_CLOSE_PATH_NV, 'M', 'C', 'C', 'Z'}; // character aliases 1113 | static const float scale = 1.0f / 500.0f; 1114 | static const float x0 = 250.0f; 1115 | static const float y0 = 250.0f; 1116 | #define COORD(x, y) \ 1117 | { \ 1118 | scale*(x - x0), scale*(y - y0) \ 1119 | } 1120 | static const GLfloat pathCoords[12][2] = {COORD(100, 180), COORD(40, 10), COORD(190, 120), COORD(10, 120), 1121 | COORD(160, 10), COORD(300, 300), COORD(100, 400), COORD(100, 200), 1122 | COORD(300, 100), COORD(500, 200), COORD(500, 400), COORD(300, 300)}; 1123 | glPathCommandsNV(g_pathObj, 10, pathCommands, 24, GL_FLOAT, pathCoords); 1124 | 1125 | glPathParameterfNV(g_pathObj, GL_PATH_STROKE_WIDTH_NV, 0.01f); 1126 | glPathParameteriNV(g_pathObj, GL_PATH_JOIN_STYLE_NV, GL_ROUND_NV); 1127 | } 1128 | //else { 1129 | // g_usePathObj = false; 1130 | //} 1131 | // 1132 | // NV_framebuffer_mixed_samples 1133 | // 1134 | // TODO check GL_NV_framebuffer_mixed_samples 1135 | { 1136 | g_MSAARaster = 8; 1137 | //glEnable(GL_RASTER_MULTISAMPLE); 1138 | //glRasterSamplesEXT(g_MSAARaster, GL_TRUE); 1139 | glCoverageModulationNV(GL_RGBA); 1140 | LOGI("GL_NV_framebuffer_mixed_samples detected: color MSAA= %d; MSAA for DST=%d\n", g_MSAAVal[g_CurMSAAColor], g_MSAARaster); 1141 | } 1142 | // -------------------------------------------- 1143 | // FBOs 1144 | // 1145 | buildRenderTargets(getWidth(), getHeight()); 1146 | 1147 | m_validated = true; 1148 | return true; 1149 | } 1150 | //------------------------------------------------------------------------------ 1151 | void MyWindow::onWindowClose() 1152 | { 1153 | s_profiler.deinit(); 1154 | ImGui::ShutdownGL(); 1155 | AppWindowCameraInertia::onWindowClose(); 1156 | m_contextWindowGL.deinit(); 1157 | } 1158 | 1159 | //------------------------------------------------------------------------------ 1160 | void MyWindow::onWindowResize(int w, int h) 1161 | { 1162 | AppWindowCameraInertia::onWindowResize(w, h); 1163 | glMatrixMode(GL_PROJECTION); 1164 | glLoadMatrixf(glm::value_ptr(m_projection)); 1165 | glMatrixMode(GL_MODELVIEW); 1166 | // 1167 | // rebuild the FBOs to match the new size 1168 | // 1169 | if(m_validated) 1170 | buildRenderTargets(w, h); 1171 | } 1172 | 1173 | //------------------------------------------------------------------------------ 1174 | #define KEYTAU 0.10f 1175 | void MyWindow::onKeyboard(NVPWindow::KeyCode key, MyWindow::ButtonAction action, int mods, int x, int y) 1176 | { 1177 | AppWindowCameraInertia::onKeyboard(key, action, mods, x, y); 1178 | if(action == MyWindow::BUTTON_RELEASE) 1179 | return; 1180 | 1181 | switch(key) 1182 | { 1183 | case NVPWindow::KEY_F1: 1184 | s_profiler.reset(1); 1185 | break; 1186 | //... 1187 | case NVPWindow::KEY_F12: 1188 | break; 1189 | } 1190 | } 1191 | //------------------------------------------------------------------------------ 1192 | void MyWindow::onKeyboardChar(unsigned char key, int mods, int x, int y) 1193 | { 1194 | AppWindowCameraInertia::onKeyboardChar(key, mods, x, y); 1195 | switch(key) 1196 | { 1197 | case '1': 1198 | blitMode = RESOLVEWITHBLIT; 1199 | LOGI("blitting using framebufferblit()\n"); 1200 | break; 1201 | case '2': 1202 | blitMode = RESOLVEWITHSHADERTEX; 1203 | LOGI("blitting using fullscreenquad and texture\n"); 1204 | break; 1205 | case '3': 1206 | blitMode = RESOLVEWITHSHADERIMAGE; 1207 | LOGI("blitting using fullscreenquad and image\n"); 1208 | break; 1209 | case '4': 1210 | blitMode = RESOLVERGBATOBACKBUFFER; 1211 | LOGI("blitting using fullscreenquad and image to backbuffer\n"); 1212 | break; 1213 | case '0': 1214 | m_camera.print_look_at(); 1215 | break; 1216 | case 'h': 1217 | s_helpText ^= 1; 1218 | break; 1219 | case ' ': 1220 | s_bCameraAnim ^= 1; 1221 | break; 1222 | case '`': 1223 | case 'u': 1224 | g_buseUI ^= 1; 1225 | break; 1226 | default: 1227 | break; 1228 | } 1229 | } 1230 | 1231 | ////////////////////////////////////////////////////////////////////////////// 1232 | // Circles 1233 | // 1234 | void beginCircles() 1235 | { 1236 | glDisable(GL_STENCIL_TEST); 1237 | if(mrtMode == RENDER1STEPRGBA) // in RGBA, only provide the simple rendering to one render-target, using RGBA 1238 | g_prog_Cst_RGBA.enable(); 1239 | else 1240 | g_prog_Cst_OneMinusCMYK_A.enable(); // using g_glslf_OneMinusCMYK_A 1241 | glBindBuffer(GL_ARRAY_BUFFER, g_vboCircle); 1242 | glEnableVertexAttribArray(0); 1243 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), NULL); 1244 | } 1245 | void drawFilledCircle(glm::mat4 mWVP, glm::vec3& p, float scale, glm::vec4& CMYK, float alpha) 1246 | { 1247 | mWVP = glm::translate(mWVP, p); 1248 | mWVP = glm::scale(mWVP, glm::vec3(scale)); 1249 | g_prog_Cst_OneMinusCMYK_A.setUniformMatrix4fv("mWVP", glm::value_ptr(mWVP), false); 1250 | g_prog_Cst_OneMinusCMYK_A.setUniform1f("alpha", alpha); 1251 | if(mrtMode == RENDER1STEPRGBA) // in RGBA, only provide the simple rendering to one render-target, using RGBA 1252 | { 1253 | glm::vec3 RGB = convertCMYK2RGB(CMYK); 1254 | g_prog_Cst_RGBA.setUniform4f("RGBA", RGB[0], RGB[1], RGB[2], alpha); 1255 | glDrawArrays(GL_TRIANGLE_FAN, 0, SUBDIVS + 2); 1256 | g_prog_Cst_RGBA.setUniform4f("RGBA", 0.0f, 0.0f, 0.0f, alpha); 1257 | glDrawArrays(GL_LINE_STRIP, 1, SUBDIVS + 1); 1258 | } 1259 | else if(mrtMode == RENDER1STEP) 1260 | { 1261 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", CMYK[0], CMYK[1], CMYK[2], CMYK[3]); 1262 | glDrawArrays(GL_TRIANGLE_FAN, 0, SUBDIVS + 2); 1263 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", 0.0f, 0.0f, 0.0f, 1.0f); 1264 | glDrawArrays(GL_LINE_STRIP, 1, SUBDIVS + 1); 1265 | } 1266 | else 1267 | { 1268 | glDrawBuffer(GL_COLOR_ATTACHMENT0); 1269 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", CMYK[0], CMYK[1], CMYK[2]); 1270 | glDrawArrays(GL_TRIANGLE_FAN, 0, SUBDIVS + 2); 1271 | if(g_curBlendEquation > 0) 1272 | glBlendBarrierNV(); 1273 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", 0.0f, 0.0f, 0.0f); 1274 | glDrawArrays(GL_LINE_STRIP, 1, SUBDIVS + 1); 1275 | if(g_curBlendEquation > 0) 1276 | glBlendBarrierNV(); 1277 | glDrawBuffer(GL_COLOR_ATTACHMENT1); 1278 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", CMYK[3]); 1279 | glDrawArrays(GL_TRIANGLE_FAN, 0, SUBDIVS + 2); 1280 | if(g_curBlendEquation > 0) 1281 | glBlendBarrierNV(); 1282 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", 1.0f); 1283 | glDrawArrays(GL_LINE_STRIP, 1, SUBDIVS + 1); 1284 | if(g_curBlendEquation > 0) 1285 | glBlendBarrierNV(); 1286 | } 1287 | } 1288 | void endCircles() 1289 | { 1290 | glBindBuffer(GL_ARRAY_BUFFER, 0); 1291 | glDisableVertexAttribArray(0); 1292 | if(mrtMode == RENDER1STEPRGBA) // in RGBA, only provide the simple rendering to one render-target, using RGBA 1293 | g_prog_Cst_RGBA.enable(); 1294 | else 1295 | g_prog_Cst_OneMinusCMYK_A.disable(); 1296 | } 1297 | ////////////////////////////////////////////////////////////////////////////// 1298 | // simple path object 1299 | // http://developer.download.nvidia.com/assets/gamedev/files/GL_NV_path_rendering.txt 1300 | // 1301 | void beginPath(glm::mat4& mWV) 1302 | { 1303 | glEnable(GL_STENCIL_TEST); 1304 | glLoadMatrixf(glm::value_ptr(mWV)); 1305 | if(mrtMode == RENDER1STEPRGBA) // in RGBA, only provide the simple rendering to one render-target, using RGBA 1306 | g_progPR_Cst_RGBA.enable(); 1307 | else 1308 | g_progPR_Cst_OneMinusCMYK_A.enable(); 1309 | } 1310 | void drawPath(glm::vec3& p, float scale, glm::vec4& CMYK, float alpha) 1311 | { 1312 | glDisableVertexAttribArray(0); 1313 | glPushMatrix(); 1314 | glTranslatef(p.x, p.y, p.z); 1315 | glScalef(scale, scale, scale); 1316 | glPathStencilFuncNV(GL_ALWAYS, 0, 0xFF); 1317 | 1318 | glStencilFillPathNV(g_pathObj, GL_INVERT /*GL_COUNT_UP_NV*/, 0xFF); 1319 | glStencilFunc(GL_NOTEQUAL, /*stencil_ref*/ 0, /*read_mask*/ 0xFF); 1320 | if(mrtMode == RENDER1STEPRGBA) // in RGBA, only provide the simple rendering to one render-target, using RGBA 1321 | { 1322 | glm::vec3 RGB = convertCMYK2RGB(CMYK); 1323 | g_progPR_Cst_RGBA.setUniform4f("RGBA", RGB[0], RGB[1], RGB[2], alpha); 1324 | glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // sfail: s failed, dpfail: s passed/d failed, dppass: s and d passed 1325 | glCoverFillPathNV(g_pathObj, GL_CONVEX_HULL_NV); 1326 | } 1327 | else if(mrtMode == RENDER1STEP) 1328 | { 1329 | g_progPR_Cst_OneMinusCMYK_A.setUniform1f("alpha", alpha); 1330 | g_progPR_Cst_OneMinusCMYK_A.setUniform4f("CMYK", CMYK[0], CMYK[1], CMYK[2], CMYK[3]); 1331 | glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // sfail: s failed, dpfail: s passed/d failed, dppass: s and d passed 1332 | glCoverFillPathNV(g_pathObj, GL_CONVEX_HULL_NV); 1333 | } 1334 | else //if(mrtMode == RENDER2STEPS) 1335 | { 1336 | g_progPR_Cst_OneMinusCMYK_A.setUniform1f("alpha", alpha); 1337 | g_progPR_Cst_OneMinusCMYK_A.setUniform4f("CMYK", CMYK[0], CMYK[1], CMYK[2]); 1338 | glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // sfail: s failed, dpfail: s passed/d failed, dppass: s and d passed 1339 | glDrawBuffer(GL_COLOR_ATTACHMENT0); 1340 | glCoverFillPathNV(g_pathObj, GL_CONVEX_HULL_NV); 1341 | g_progPR_Cst_OneMinusCMYK_A.setUniform4f("CMYK", CMYK[3]); 1342 | glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // sfail: s failed, dpfail: s passed/d failed, dppass: s and d passed 1343 | glDrawBuffer(GL_COLOR_ATTACHMENT1); 1344 | glCoverFillPathNV(g_pathObj, GL_CONVEX_HULL_NV); 1345 | } 1346 | 1347 | glStencilStrokePathNV(g_pathObj, GL_INVERT /*GL_COUNT_UP_NV*/, 0xFF); 1348 | if(mrtMode == RENDER1STEPRGBA) // in RGBA, only provide the simple rendering to one render-target, using RGBA 1349 | { 1350 | g_progPR_Cst_RGBA.setUniform4f("RGBA", 0.0f, 0.0f, 0.0f, alpha); 1351 | glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // sfail: s failed, dpfail: s passed/d failed, dppass: s and d passed 1352 | glCoverFillPathNV(g_pathObj, GL_CONVEX_HULL_NV); 1353 | } 1354 | else if(mrtMode == RENDER1STEP) 1355 | { 1356 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", 0.0f, 0.0f, 0.0f, 1.0f); 1357 | glCoverStrokePathNV(g_pathObj, GL_CONVEX_HULL_NV); 1358 | } 1359 | else //if(mrtMode == RENDER2STEPS) 1360 | { 1361 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", 0.0f, 0.0f, 0.0f); 1362 | glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // sfail: s failed, dpfail: s passed/d failed, dppass: s and d passed 1363 | glDrawBuffer(GL_COLOR_ATTACHMENT0); 1364 | glCoverStrokePathNV(g_pathObj, GL_CONVEX_HULL_NV); 1365 | g_prog_Cst_OneMinusCMYK_A.setUniform4f("CMYK", /*K*/ 1.0f); 1366 | glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // sfail: s failed, dpfail: s passed/d failed, dppass: s and d passed 1367 | glDrawBuffer(GL_COLOR_ATTACHMENT1); 1368 | glCoverStrokePathNV(g_pathObj, GL_CONVEX_HULL_NV); 1369 | } 1370 | glPopMatrix(); 1371 | } 1372 | void endPath() 1373 | { 1374 | glDisable(GL_STENCIL_TEST); 1375 | if(mrtMode == RENDER1STEPRGBA) // in RGBA, only provide the simple rendering to one render-target, using RGBA 1376 | g_progPR_Cst_RGBA.disable(); 1377 | else 1378 | g_progPR_Cst_OneMinusCMYK_A.disable(); 1379 | } 1380 | ////////////////////////////////////////////////////////////////////////////// 1381 | // scene 1382 | // 1383 | 1384 | //------------------------------------------------------------------------------ 1385 | void MyWindow::renderScene() 1386 | { 1387 | PROFILE_SECTION(__FUNCTION__); 1388 | static glm::vec4 colorsCMYK[] = {glm::vec4(1, 1, 0, 0.0), glm::vec4(0, 1, 1, 0.0), glm::vec4(1, 0, 1, 0.0), 1389 | glm::vec4(1, 0, 0, 0.0), glm::vec4(0, 1, 0, 0.0), glm::vec4(0, 0, 1, 0.0), 1390 | glm::vec4(0.4f, 0, 1, 0.4f)}; 1391 | if(g_pathObj && g_usePathObj) 1392 | { 1393 | // m_projection is already in glMatrixMode(GL_PROJECTION) 1394 | beginPath(m_camera.m4_view); 1395 | { 1396 | int c = 0; 1397 | for(int y = 0; y < g_NObjs; y++) 1398 | for(int x = 0; x < g_NObjs; x++) 1399 | { 1400 | glm::vec3 p(-1.0f + 2.0f * (float)x / (float)g_NObjs, -1.0f + 2.0f * (float)y / (float)g_NObjs, 0); 1401 | drawPath(p, 1.0f, colorsCMYK[c], g_alpha); 1402 | c = (c + 1) % 7; 1403 | } 1404 | } 1405 | endPath(); 1406 | } 1407 | else 1408 | { 1409 | glm::mat4 mVP; 1410 | mVP = m_projection * m_camera.m4_view; 1411 | beginCircles(); 1412 | { 1413 | int c = 0; 1414 | for(int y = 0; y < g_NObjs; y++) 1415 | for(int x = 0; x < g_NObjs; x++) 1416 | { 1417 | glm::vec3 p(-1.0f + 2.0f * (float)x / (float)g_NObjs, -1.0f + 2.0f * (float)y / (float)g_NObjs, 0); 1418 | drawFilledCircle(mVP, p, 1.0f, colorsCMYK[c], g_alpha); 1419 | c = (c + 1) % 7; 1420 | } 1421 | } 1422 | endCircles(); 1423 | } 1424 | } 1425 | 1426 | //------------------------------------------------------------------------------ 1427 | void renderFullscreenQuad() 1428 | { 1429 | glBindBuffer(GL_ARRAY_BUFFER, g_vboQuad); 1430 | glEnableVertexAttribArray(0); 1431 | glVertexAttribIPointer(0, 2, GL_INT, sizeof(int) * 2, NULL); 1432 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1433 | glBindBuffer(GL_ARRAY_BUFFER, 0); 1434 | glDisableVertexAttribArray(0); 1435 | } 1436 | 1437 | //------------------------------------------------------------------------------ 1438 | void MyWindow::onWindowRefresh() 1439 | { 1440 | AppWindowCameraInertia::onWindowRefresh(); 1441 | float dt = (float)m_realtime.getFrameDT(); 1442 | // 1443 | // Simple camera change for animation 1444 | // 1445 | if(s_bCameraAnim) 1446 | { 1447 | s_cameraAnimIntervals -= dt; 1448 | if(s_cameraAnimIntervals <= 0.0) 1449 | { 1450 | s_cameraAnimIntervals = ANIMINTERVALL; 1451 | m_camera.look_at(s_cameraAnim[s_cameraAnimItem].eye, s_cameraAnim[s_cameraAnimItem].focus); 1452 | s_cameraAnimItem++; 1453 | if(s_cameraAnimItem >= s_cameraAnimItems) 1454 | s_cameraAnimItem = 0; 1455 | } 1456 | } 1457 | s_profiler.beginFrame(); 1458 | { 1459 | PROFILE_SECTION("frame"); 1460 | NXPROFILEFUNC("frame"); 1461 | //glEnable(GL_FRAMEBUFFER_SRGB); 1462 | // 1463 | // Render with some CMYK colored primitives into a 2-render target destination 1464 | // the result will be stored in 1-(value) 1465 | // 1466 | const glm::vec4 bgngCMYK(0.0f, 0.0f, 0.0f, 0.0f); 1467 | glDisable(GL_DEPTH_TEST); 1468 | 1469 | // Blending 1470 | if(g_blendEnable) 1471 | glEnable(GL_BLEND); 1472 | else 1473 | glDisable(GL_BLEND); 1474 | glBlendEquation(blendequations[g_curBlendEquation]); 1475 | if(glBlendParameteriNV != NULL) 1476 | glBlendParameteriNV(GL_BLEND_PREMULTIPLIED_SRC_NV, GL_FALSE); 1477 | glBlendFunc(blendfuncs[g_blendSRC], blendfuncs[g_blendDST]); 1478 | 1479 | // Bind the render targets 1480 | glBindFramebuffer(GL_FRAMEBUFFER, FBO::TexMS_CMYA_KA_DST); 1481 | 1482 | // Clear for RT#0 1483 | glDrawBuffer(GL_COLOR_ATTACHMENT0); 1484 | glClearColor(1.0f - bgngCMYK.x, 1.0f - bgngCMYK.y, 1.0f - bgngCMYK.z, 1.0f); 1485 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 1486 | // Clear for RT#1 1487 | glDrawBuffer(GL_COLOR_ATTACHMENT1); 1488 | glClearColor(1.0f - bgngCMYK.w, 0.0f, 0.0f, 1.0f); 1489 | glClear(GL_COLOR_BUFFER_BIT); 1490 | 1491 | switch(mrtMode) 1492 | { 1493 | case RENDER1STEP: 1494 | // we can do early Activation of RT#0 & RT#1 1495 | glDrawBuffers(2, drawBuffers); 1496 | renderScene(); 1497 | break; 1498 | case RENDER2STEPS: 1499 | // Drawbuffer target must be setup later 1500 | renderScene(); 1501 | break; 1502 | case RENDER1STEPRGBA: 1503 | // we can do early Activation of RT#0 1504 | glDrawBuffer(GL_COLOR_ATTACHMENT0); 1505 | renderScene(); 1506 | break; 1507 | } 1508 | // back to regular default 1509 | glBlendEquation(GL_FUNC_ADD); 1510 | glDisable(GL_BLEND); 1511 | // Now we have rendered things in 2 render targets 1512 | // 2 solutions: 1513 | // 1- resolve to 2 intermediate renter Textures 1514 | // 2- use a Shader to directly read the 2 MSAA Textures and resolve on the flight 1515 | // Done. Back to the backbuffer 1516 | switch(blitMode) 1517 | { 1518 | case RESOLVEWITHBLIT: 1519 | glDisable(GL_FRAMEBUFFER_SRGB); 1520 | // use the HW Blit to resolve MSAA to regular texture 1521 | glDrawBuffers(1, drawBuffers); 1522 | // Render Target 1 1523 | blitFBONearest(FBO::TexMS_CMYA, FBO::Tex_CMYA, 0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight()); 1524 | // Render Target 2 1525 | blitFBONearest(FBO::TexMS_KA, FBO::Tex_KA, 0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight()); 1526 | // switch back to our backbuffer and perform the conversion to RGBA 1527 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 1528 | g_progTex_CMYA_KA_2_RGBA.enable(); // using g_glslf_Tex_CMYA_KA_2_RGBA 1529 | g_progTex_CMYA_KA_2_RGBA.setUniform2i("viewportSz", getWidth(), getHeight()); 1530 | g_progTex_CMYA_KA_2_RGBA.setUniform4f("CMYK_Mask", g_activeC ? 1.0f : 0.0f, g_activeM ? 1.0f : 0.0f, 1531 | g_activeY ? 1.0f : 0.0f, g_activeK ? 1.0f : 0.0f); 1532 | g_progTex_CMYA_KA_2_RGBA.bindTexture("sampler_CMYA", Texture::CMYA, GL_TEXTURE_2D, 0); 1533 | g_progTex_CMYA_KA_2_RGBA.bindTexture("sampler_KA", Texture::KA, GL_TEXTURE_2D, 1); 1534 | // Fullscreen quad 1535 | renderFullscreenQuad(); 1536 | break; 1537 | case RESOLVEWITHSHADERTEX: 1538 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 1539 | g_progTexMS_CMYA_KA_2_RGBA[g_CurMSAAColor].enable(); // using g_glslf_TexMS_CMYA_KA_2_RGBA 1540 | g_progTexMS_CMYA_KA_2_RGBA[g_CurMSAAColor].setUniform2i("viewportSz", getWidth(), getHeight()); 1541 | g_progTexMS_CMYA_KA_2_RGBA[g_CurMSAAColor].setUniform4f("CMYK_Mask", g_activeC ? 1.0f : 0.0f, g_activeM ? 1.0f : 0.0f, 1542 | g_activeY ? 1.0f : 0.0f, g_activeK ? 1.0f : 0.0f); 1543 | g_progTexMS_CMYA_KA_2_RGBA[g_CurMSAAColor].bindTexture("samplerMS_CMYA", Texture::MS_CMYA, GL_TEXTURE_2D_MULTISAMPLE, 0); 1544 | g_progTexMS_CMYA_KA_2_RGBA[g_CurMSAAColor].bindTexture("samplerMS_KA", Texture::MS_KA, GL_TEXTURE_2D_MULTISAMPLE, 1); 1545 | // Fullscreen quad 1546 | renderFullscreenQuad(); 1547 | break; 1548 | case RESOLVEWITHSHADERIMAGE: 1549 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 1550 | if(g_progImageMS_CMYA_KA_2_RGBA[g_CurMSAAColor].getProgId()) 1551 | { 1552 | g_progImageMS_CMYA_KA_2_RGBA[g_CurMSAAColor].enable(); 1553 | g_progImageMS_CMYA_KA_2_RGBA[g_CurMSAAColor].setUniform2i("viewportSz", getWidth(), getHeight()); 1554 | g_progImageMS_CMYA_KA_2_RGBA[g_CurMSAAColor].setUniform4f("CMYK_Mask", g_activeC ? 1.0f : 0.0f, g_activeM ? 1.0f : 0.0f, 1555 | g_activeY ? 1.0f : 0.0f, g_activeK ? 1.0f : 0.0f); 1556 | g_progImageMS_CMYA_KA_2_RGBA[g_CurMSAAColor].bindImage("imageMS_CMYA", 0, Texture::MS_CMYA, 0, GL_FALSE, 0, 1557 | GL_READ_ONLY, GL_RGBA8); 1558 | g_progImageMS_CMYA_KA_2_RGBA[g_CurMSAAColor].bindImage("imageMS_KA", 1, Texture::MS_KA, 0, GL_FALSE, 0, 1559 | GL_READ_ONLY, GL_RGBA8); 1560 | // Fullscreen quad 1561 | renderFullscreenQuad(); 1562 | } 1563 | else 1564 | { 1565 | glClearColor(1.0, 0.0, 0.0, 1.0f); 1566 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 1567 | } 1568 | break; 1569 | case RESOLVERGBATOBACKBUFFER: 1570 | blitFBONearest(FBO::TexMS_RGBA, 0 /*backbuffer*/, 0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight()); 1571 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 1572 | break; 1573 | } 1574 | if(g_buseUI) 1575 | { 1576 | int width = getWidth(); 1577 | int height = getHeight(); 1578 | processUI(width, height, dt); 1579 | ImDrawData* imguiDrawData; 1580 | ImGui::Render(); 1581 | imguiDrawData = ImGui::GetDrawData(); 1582 | ImGui::RenderDrawDataGL(imguiDrawData); 1583 | ImGui::EndFrame(); 1584 | } 1585 | } //PROFILE_SECTION("frame"); 1586 | m_contextWindowGL.swapBuffers(); 1587 | s_profiler.endFrame(); 1588 | } 1589 | ///////////////////////////////////////////////////////////////////////// 1590 | // Main initialization point 1591 | // 1592 | int main(int argc, const char** argv) 1593 | { 1594 | NVPSystem system(PROJECT_NAME); 1595 | 1596 | // you can create more than only one 1597 | static MyWindow myWindow; 1598 | 1599 | nvgl::ContextWindowCreateInfo context(4, //major; 1600 | 3, //minor; 1601 | false, //core; 1602 | 8, //MSAA; 1603 | 24, //depth bits 1604 | 8, //stencil bits 1605 | true, //debug; 1606 | false, //robust; 1607 | false, //forward; 1608 | false, //stereo 1609 | NULL //share; 1610 | ); 1611 | 1612 | if(!myWindow.open(0, 0, 1280, 720, "CMYK", context)) 1613 | { 1614 | LOGE("Failed to initialize the sample\n"); 1615 | return EXIT_FAILURE; 1616 | } 1617 | 1618 | myWindow.m_contextWindowGL.makeContextCurrent(); 1619 | myWindow.m_contextWindowGL.swapInterval(0); 1620 | myWindow.onWindowResize(myWindow.getWidth(), myWindow.getHeight()); 1621 | 1622 | while(myWindow.pollEvents()) 1623 | { 1624 | myWindow.idle(); 1625 | if(myWindow.m_renderCnt > 0) 1626 | { 1627 | myWindow.m_renderCnt--; 1628 | myWindow.onWindowRefresh(); 1629 | } 1630 | 1631 | if(myWindow.m_guiRegistry.checkValueChange(COMBO_MSAACOL)) 1632 | { 1633 | if(!g_has_GL_NV_framebuffer_mixed_samples) 1634 | { 1635 | g_MSAARaster = g_MSAAVal[g_CurMSAAColor]; 1636 | } 1637 | buildRenderTargets(myWindow.getWidth(), myWindow.getHeight()); 1638 | } 1639 | if(myWindow.m_guiRegistry.checkValueChange(COMBO_MSAARAST)) 1640 | { 1641 | buildRenderTargets(myWindow.getWidth(), myWindow.getHeight()); 1642 | } 1643 | if(myWindow.m_guiRegistry.checkValueChange(COMBO_BLENDEQ)) 1644 | { 1645 | if(g_curBlendEquation == GL_ZERO) 1646 | { // CHECK THIS!! 1647 | if(mrtMode != RENDER1STEPRGBA) 1648 | mrtMode = RENDER2STEPS; // need to render only in one render-target at a time 1649 | } 1650 | } 1651 | } 1652 | return EXIT_SUCCESS; 1653 | } 1654 | --------------------------------------------------------------------------------