{"id":56,"date":"2022-07-25T12:33:21","date_gmt":"2022-07-25T12:33:21","guid":{"rendered":"https:\/\/blogs.scummvm.org\/grisenti\/?p=56"},"modified":"2022-07-31T20:33:49","modified_gmt":"2022-07-31T20:33:49","slug":"working-on-shaders","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/grisenti\/2022\/07\/25\/working-on-shaders\/","title":{"rendered":"Working on shaders"},"content":{"rendered":"<p><span data-contrast=\"auto\">This week I worked on the shader system of the engine. The first thing I did was to translate the shader from the CG language, which is very similar to HLSL (the shading language used in Direct3D) to GLSL, the OpenGL shading language. The two are somewhat similar but there are some important differences. The most apparent one by looking at the code side by side is that in CG, the shader parameters &#8211; input, outputs and uniforms (variables constant throughout the execution on a set of shader inputs like the vertices of a mesh) &#8211; are specified in the signature for the main function, while in GLSL they are specified in the global scope.\u00a0<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">The name of types and build-in functions is also different. An example of this are the floating-point vector types which in CG are called <code>floatn<\/code>, where n is the number of components (eg. <code>float4<\/code>), while in GLSL the equivalent would be <code>vecn<\/code>. Also, some of the base types present in CG are not available in GLSL, like the <code>half<\/code> and <code>fixed<\/code> real number types, thought these are only used for optimization reasons, so I replaced them with the <code>float<\/code> type. Another important difference is in the conversion between types. In GC the following line is valid:\u00a0 <\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\"><br \/>\n<\/span><\/p>\n<pre style=\"color: #d1d1d1;background: #1E1E1E\" data-darkreader-inline-color=\"\" data-darkreader-inline-bgcolor=\"\" data-darkreader-inline-bgimage=\"\">float3 offset <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">=<\/span> <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span>tex2D<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span>refractMap<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">,<\/span> uv2<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">) <\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">* <\/span><span style=\"color: #008c00\" data-darkreader-inline-color=\"\">2<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">)<\/span> <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">-<\/span> <span style=\"color: #008c00\" data-darkreader-inline-color=\"\">1<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">)<\/span> <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">*<\/span> alpha <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">*<\/span> color<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">.<\/span>w<span style=\"color: #b060b0\" data-darkreader-inline-color=\"\">;<\/span> \r\n<\/pre>\n<p><span data-contrast=\"auto\">While in GLSL it must be written as:<\/span><\/p>\n<pre style=\"color: #d1d1d1;background: #1E1E1E\" data-darkreader-inline-color=\"\" data-darkreader-inline-bgcolor=\"\" data-darkreader-inline-bgimage=\"\">vec3 offset <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">=<\/span> vec3<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span>texture<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span>refractMap<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">,<\/span> uv2<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">) <\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">* <\/span><span style=\"color: #009f00\" data-darkreader-inline-color=\"\">2<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">)<\/span> <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">-<\/span> <span style=\"color: #009f00\" data-darkreader-inline-color=\"\">1<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">)<\/span> <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">*<\/span> alpha <span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">*<\/span> color<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">.<\/span>w<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">)<\/span><span style=\"color: #b060b0\" data-darkreader-inline-color=\"\">;<\/span>\r\n<\/pre>\n<p style=\"font-size: 15px\">(both texture functions return a 4-component vector, but in CG this gets comverted <span class=\"TextRun SCXW72603671 BCX2\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW72603671 BCX2\">implicitly <\/span><\/span>to a 3-component vector while in GLSL the operation must be explicit)<\/p>\n<p>The last interesting difference in the shader types is in the way data is passed to the vertex shader and between shader stages. In GLSL 1.2 this is done by specifying the relevant data as an <code>in<\/code> or <code>out<\/code> parameter. In the case of data being passed by the vertex shader to the fragment shader, this needs to be declared as an <code>out<\/code> parameter in first and as an <code>in<\/code> parameter in the second, in both with the same name and type. This last requirement is not present in CG, instead the out and in parameters are supplemented with an additional specifier:<\/p>\n<pre style=\"color: #d1d1d1;background: #1E1E1E\" data-darkreader-inline-color=\"\" data-darkreader-inline-bgcolor=\"\" data-darkreader-inline-bgimage=\"\"><span style=\"color: #9999a9\" data-darkreader-inline-color=\"\">\/\/vertex shader <\/span>\r\n<span style=\"color: #e66170;font-weight: bold\" data-darkreader-inline-color=\"\">void<\/span> <span style=\"color: #e66170;font-weight: bold\" data-darkreader-inline-color=\"\">main<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span>out float4 oPos <span style=\"color: #b060b0\" data-darkreader-inline-color=\"\">:<\/span> POSITION<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">)<\/span>\r\n<span style=\"color: #9999a9\" data-darkreader-inline-color=\"\">\/\/ fragment shader  <\/span>\r\n<span style=\"color: #e66170;font-weight: bold\" data-darkreader-inline-color=\"\">void<\/span> <span style=\"color: #e66170;font-weight: bold\" data-darkreader-inline-color=\"\">main<\/span><span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">(<\/span>in float3 iPos <span style=\"color: #b060b0\" data-darkreader-inline-color=\"\">:<\/span> POSITION<span style=\"color: #d2cd86\" data-darkreader-inline-color=\"\">)<\/span><\/pre>\n<p>The next task I worked on was removing the two-shader system that was present in the engine, created by the fact that CG shaders can be activated independently of each other while for GLSL shaders this must be done on the combination of vertex and fragment. For now I\u2019ve only implemented the code required for the highest setting because I had some doubts about the others.<\/p>\n<p><span data-contrast=\"auto\">For now, all the shaders necessary for the first scene compile but they produce broken output. Next week I\u2019ll work on fixing them and implement the material classes needed for the high and medium graphics settings. After that I will probably get back to physics debugging where a problem with player-objects interaction makes the game hard to play. <\/span><\/p>\n<p>As an update for the notebook problem I described in the previous blog post, this has now been fixed thanks to aquadran and the HPL1R project (<a href=\"https:\/\/github.com\/zenmumbler\/HPL1R\">https:\/\/github.com\/zenmumbler\/HPL1R<\/a>). For those who didn\u2019t read it, the problem was that some game items, including the notebook on the table at the start, which is necessary to go forward in the game, disappeared. The bug turned out to be in one of the mesh loading classes (<code>MeshLoaderCollada<\/code>), that created broken geometry for some scaled objects.<span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p>Thanks for reading.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h4>Corrections:<\/h4>\n<p><span data-contrast=\"auto\">The part on conversions has been updated to remove unnecessary conversions that I initially thought were necessary. <\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This week I worked on the shader system of the engine. The first thing I did was to translate the shader from the CG language, which is very similar to HLSL (the shading language used in Direct3D) to GLSL, the OpenGL shading language. The two are somewhat similar but there are some important differences. The [&hellip;]<\/p>\n","protected":false},"author":13,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-56","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/posts\/56","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/comments?post=56"}],"version-history":[{"count":6,"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/posts\/56\/revisions"}],"predecessor-version":[{"id":63,"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/posts\/56\/revisions\/63"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/media?parent=56"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/categories?post=56"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/grisenti\/wp-json\/wp\/v2\/tags?post=56"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}