Testing OpenGL Fragment Shader Programs in the Qt Quick Engine

Testing OpenGL shader programs has become a lot easier ever since the advent of WebGL technology, and it's implementation across most major web browsers. In the past, developers would have had to write code to initialize an OpenGL rendering context on a display, set up the world  and viewport dimensions before writing utility methods or classes (in C++) for compiling, linking and using shader programs.

Luckily, ever since the emergence of WebGL and it's adoption across most web browsers, web applications have appeared such as shadertoy, which allows artists to focus on developing fragment shaders in their web browser.

For those that want to test fragment shader programs natively, that is, within a regular OpenGL rendering context in a window created by the operating system, you can do so with the QML scripting engine provided by Qt's SDK. QML, or Quick Markup Language, is designed for creating user interfaces.

Fragment shader programs are hosted in a fragmentShader attribute, and are modified by ShaderEffect elements, and two neat aspects of them is that they can be nested within UI components, and that accessing uniform variables is pretty easy. In this example code I have animated a property of a fragment shader variable:

import QtQuick 2.0
import QtQuick.Controls 2.2

ApplicationWindow {
	id: root
	visible: true
	width: 1024
	height: 768
	ShaderEffect {
		width: parent.width; height: parent.height
		blending: false
		property real time: 0
		property vector2d resolution: "1024,768"
		property real center: 0.1
		NumberAnimation on center {
			loops: Animation.Infinite
			from: 1
			to: -0.1
			duration: 4000
		}
		
		Timer {
			interval: 20; running: true; repeat: true
            onTriggered: { if (parent.time < 1.01) parent.time += 0.01; else parent.time = 0; }
        }

  Slider {
      id: sliderCenter
      x: 8
      y: 720
      from: 0.10
      value: 1.0
      onValueChanged: parent.center = value
  }
  fragmentShader: "
			#ifdef GL_ES
			precision mediump float;
			#endif

			uniform float time;
			uniform float center;
			uniform vec2 mouse;
			uniform vec2 resolution;

			void main()
			{
				vec2 r = resolution,
				o = gl_FragCoord.xy - r/2.;
				o = vec2(length((o)) / r.y - center, atan(o.y,o.x));    
				vec4 s = .1*cos(1.618*vec4(0,1,2,3) + time * 3. + o.y + sin(o.y) * sin(time)*2.),
				e = s.yzwx, 
				f = min(o.x-s,e-o.x);
				gl_FragColor = dot(clamp(f*r.y,0.,1.), 60.*(s-e)) * (s-.1) - f;
			}"
		}
}

 

The latest Qt SDK containing the qml executable can be retrieved from https://www.qt.io/