Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_opengl_shader_loader.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2016 Julian Thijssen <julianthijssen@gmail.com>
3 * SPDX-FileCopyrightText: 2023 L. E. Segovia <amy@amyspark.me>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
9
10#include "opengl/kis_opengl.h"
11#include "kis_config.h"
12
13#include <config-ocio.h>
14
15#include <QFile>
16#include <QMessageBox>
17#include <KLocalizedString>
18
19#define PROGRAM_VERTEX_ATTRIBUTE 0
20#define PROGRAM_TEXCOORD_ATTRIBUTE 1
21
22// Mapping of uniforms to uniform names
23std::map<Uniform, const char *> KisShaderProgram::names = {
24 {ModelViewProjection, "modelViewProjection"},
25 {TextureMatrix, "textureMatrix"},
26 {ViewportScale, "viewportScale"},
27 {TexelSize, "texelSize"},
28 {Texture0, "texture0"},
29 {Texture1, "texture1"},
30 {FixedLodLevel, "fixedLodLevel"},
31 {FragmentColor, "fragColor"}
32};
33
44KisShaderProgram *KisOpenGLShaderLoader::loadShader(QString vertPath, QString fragPath,
45 QByteArray vertHeader, QByteArray fragHeader)
46{
47 bool result;
48
49 KisShaderProgram *shader = new KisShaderProgram();
50
51 // Load vertex shader
52 QByteArray vertSource;
53
55 vertSource.append("#version 300 es\n");
56 } else {
57#ifdef Q_OS_MACOS
58 vertSource.append(KisOpenGL::hasOpenGL3() ? "#version 150 core\n" : "#version 120\n");
59 vertSource.append("#define texture2D texture\n");
60 vertSource.append("#define texture3D texture\n");
61#else
62 vertSource.append(KisOpenGL::supportsLoD() ? "#version 130\n" : "#version 120\n");
63#endif
64 }
65 vertSource.append(vertHeader);
66 QFile vertexShaderFile(":/" + vertPath);
67 vertexShaderFile.open(QIODevice::ReadOnly);
68 vertSource.append(vertexShaderFile.readAll());
69
70 result = shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertSource);
71 if (!result)
72 throw ShaderLoaderException(QString("%1: %2 - Cause: %3").arg("Failed to add vertex shader source from file", vertPath, shader->log()));
73
74 // Load fragment shader
75 QByteArray fragSource;
76
78 fragSource.append("#version 300 es\n");
80 fragSource.append("#extension GL_EXT_shader_texture_lod : enable\n");
81 }
82 fragSource.append(
83 "precision mediump float;\n"
84 "precision mediump sampler3D;\n");
85
86 // OpenColorIO doesn't support OpenGL ES.
87 fragSource.append("#define texture2D texture\n");
88 fragSource.append("#define texture3D texture\n");
90 fragSource.append(
91 "#if __VERSION__ < 300\n"
92 "#define textureLod texture2DLodEXT\n"
93 "#endif\n"
94 );
95 }
96 } else {
97#ifdef Q_OS_MACOS
98 fragSource.append(KisOpenGL::hasOpenGL3() ? "#version 150 core\n" : "#version 120\n");
99 fragSource.append("#define texture2D texture\n");
100 fragSource.append("#define texture3D texture\n");
101#else
102 fragSource.append(KisOpenGL::supportsLoD() ? "#version 130\n" : "#version 120\n");
103#endif
104 }
105 fragSource.append(fragHeader);
106 QFile fragmentShaderFile(":/" + fragPath);
107 fragmentShaderFile.open(QIODevice::ReadOnly);
108 fragSource.append(fragmentShaderFile.readAll());
109
110 result = shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragSource);
111 if (!result)
112 throw ShaderLoaderException(QString("%1: %2 - Cause: %3").arg("Failed to add fragment shader source from file", fragPath, shader->log()));
113
114 // Bind attributes
115 shader->bindAttributeLocation("a_vertexPosition", PROGRAM_VERTEX_ATTRIBUTE);
116 shader->bindAttributeLocation("a_textureCoordinate", PROGRAM_TEXCOORD_ATTRIBUTE);
117
118 // Link
119 result = shader->link();
120 if (!result)
121 throw ShaderLoaderException(QString("Failed to link shader: ").append(vertPath));
122
123 Q_ASSERT(shader->isLinked());
124
125 return shader;
126}
127
135{
136 QByteArray fragHeader;
137
139 fragHeader.append("#define DIRECT_LOD_FETCH\n");
140 if (useHiQualityFiltering) {
141 fragHeader.append("#define HIGHQ_SCALING\n");
142 }
143 }
144
145 // If we have an OCIO display filter and it contains a function we add
146 // it to our shader header which will sit on top of the fragment code.
147 bool haveDisplayFilter = displayFilter && !displayFilter->program().isEmpty();
148 if (haveDisplayFilter) {
149 fragHeader.append("#define USE_OCIO\n");
150#ifdef HAVE_OCIO_V2
151 fragHeader.append("#define USE_OCIO_V2\n");
152#endif
153 fragHeader.append(displayFilter->program().toLatin1());
154 }
155
156 QString vertPath, fragPath;
157 // Select appropriate shader files
159 vertPath = "matrix_transform.vert";
160 fragPath = "highq_downscale.frag";
161 } else {
162 vertPath = "matrix_transform_legacy.vert";
163 fragPath = "simple_texture_legacy.frag";
164 }
165
166 KisShaderProgram *shader = loadShader(vertPath, fragPath, QByteArray(), fragHeader);
167
168 return shader;
169}
170
176{
177 QString vertPath, fragPath;
178 // Select appropriate shader files
180 vertPath = "matrix_transform.vert";
181 fragPath = "simple_texture.frag";
182 } else {
183 vertPath = "matrix_transform_legacy.vert";
184 fragPath = "simple_texture_legacy.frag";
185 }
186
187 KisShaderProgram *shader = loadShader(vertPath, fragPath, QByteArray(), QByteArray());
188
189 return shader;
190}
191
197{
198 QString vertPath, fragPath;
199 // Select appropriate shader files
201 vertPath = "solid_color.vert";
202 fragPath = "solid_color.frag";
203 } else {
204 vertPath = "solid_color_legacy.vert";
205 fragPath = "solid_color_legacy.frag";
206 }
207
208 KisShaderProgram *shader = loadShader(vertPath, fragPath, QByteArray(), QByteArray());
209
210 return shader;
211}
KisShaderProgram * loadShader(QString vertPath, QString fragPath, QByteArray vertHeader, QByteArray fragHeader)
KisShaderProgram * loadSolidColorShader()
KisShaderProgram * loadCheckerShader()
KisShaderProgram * loadDisplayShader(QSharedPointer< KisDisplayFilter > displayFilter, bool useHiQualityFiltering)
static bool hasOpenGLES()
static bool supportsLoD()
static bool hasOpenGL3()
static std::map< Uniform, const char * > names
#define PROGRAM_TEXCOORD_ATTRIBUTE
#define PROGRAM_VERTEX_ATTRIBUTE
@ ModelViewProjection