EscapeTimeVisualWidget.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #include "EscapeTimeVisualWidget.h"
  2. #include "Bitmap.h"
  3. #include <QOpenGLShaderProgram>
  4. #include <QOpenGLContext>
  5. #include <QOpenGLFunctions>
  6. #include <vector>
  7. ETVImage::ETVImage(EscapeTimeVisualWidget& owner,
  8. const Bitmap<float>& img) :
  9. owner{ owner }
  10. {
  11. auto& gl = *owner.context()->functions();
  12. gl.glGenTextures(1, &textureId);
  13. gl.glActiveTexture(GL_TEXTURE0);
  14. gl.glBindTexture(GL_TEXTURE_2D, textureId);
  15. gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, int(img.width), int(img.height), 0, GL_RED, GL_FLOAT, img.pixels.get());
  16. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  17. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  18. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  19. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  20. gl.glBindTexture(GL_TEXTURE_2D, 0);
  21. }
  22. ETVImage::~ETVImage(void)
  23. {
  24. auto& gl = *owner.context()->functions();
  25. gl.glDeleteTextures(1, &textureId);
  26. }
  27. void ETVImage::draw(float x, float y, float w, float h,
  28. float tx, float ty, float tw, float th)
  29. {
  30. auto& gl = *owner.context()->functions();
  31. GLfloat const vertices[] = {
  32. x, y, 0.0f,
  33. x, y + h, 0.0f,
  34. x + w, y, 0.0f,
  35. x + w, y + h, 0.0f,
  36. };
  37. GLfloat const texCoords[] = {
  38. tx, ty,
  39. tx, ty + th,
  40. tx + tw, ty,
  41. tx + tw, ty + th,
  42. };
  43. QColor color{ 255, 255, 255 };
  44. auto& program = owner.program;
  45. int vertexLoc = program->attributeLocation("vertex");
  46. int texCoordsLoc = program->attributeLocation("texCoord");
  47. int colorLocation = program->uniformLocation("color");
  48. int texLoc = program->uniformLocation("tex");
  49. int gradLoc = program->uniformLocation("gradient");
  50. program->setAttributeArray(vertexLoc, vertices, 3);
  51. program->setAttributeArray(texCoordsLoc, texCoords, 2);
  52. program->enableAttributeArray(vertexLoc);
  53. program->enableAttributeArray(texCoordsLoc);
  54. program->setUniformValue(colorLocation, color);
  55. gl.glEnable(GL_TEXTURE_2D);
  56. gl.glUniform1i(texLoc, 0);
  57. gl.glUniform1i(gradLoc, 2);
  58. gl.glActiveTexture(GL_TEXTURE0);
  59. gl.glBindTexture(GL_TEXTURE_2D, textureId);
  60. gl.glActiveTexture(GL_TEXTURE2);
  61. gl.glBindTexture(GL_TEXTURE_2D, owner.gradientTextureId);
  62. gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  63. program->disableAttributeArray(vertexLoc);
  64. program->disableAttributeArray(texCoordsLoc);
  65. gl.glActiveTexture(GL_TEXTURE0);
  66. }
  67. EscapeTimeVisualWidget::EscapeTimeVisualWidget(QWidget* parent) :
  68. QOpenGLWidget{ parent },
  69. gradientNeedsUpdate{ false }
  70. {
  71. }
  72. void EscapeTimeVisualWidget::setGradient(Gradient newGradient)
  73. {
  74. this->gradient = newGradient;
  75. gradientNeedsUpdate = true;
  76. update();
  77. }
  78. const Gradient& EscapeTimeVisualWidget::getGradient(void)
  79. {
  80. return gradient;
  81. }
  82. void EscapeTimeVisualWidget::initializeGL(void)
  83. {
  84. auto& gl = *this->context()->functions();
  85. gl.glClearColor(0, 0, 0, 0);
  86. gl.glDisable(GL_DEPTH_TEST);
  87. // looks not even better
  88. //gl.glEnable(GL_FRAMEBUFFER_SRGB);
  89. //glShadeModel(GL_SMOOTH);
  90. program = new QOpenGLShaderProgram{ this->context() };
  91. bool vert = program->addShaderFromSourceCode(QOpenGLShader::Vertex,
  92. "attribute highp vec4 vertex;\n"
  93. "attribute highp vec2 texCoord;\n"
  94. "uniform highp mat4 matrix;\n"
  95. "varying highp vec2 texc;\n"
  96. "void main(void)\n"
  97. "{\n"
  98. " gl_Position = matrix * vertex;\n"
  99. " texc = texCoord;\n"
  100. "}");
  101. // TODO rewrite this monster
  102. bool frag = program->addShaderFromSourceCode(QOpenGLShader::Fragment,
  103. "#version 400\n"
  104. "uniform sampler2D gradient;\n"
  105. "uniform sampler2D tex;\n"
  106. "uniform mediump vec4 color;\n"
  107. "uniform highp float gradientScaler;\n"
  108. "varying highp vec2 texc;\n"
  109. "void main(void)\n"
  110. "{\n"
  111. " float v = texture2D(tex, texc).r;\n"
  112. " vec2 size = textureSize(tex, 0);\n"
  113. //" size = vec2(256.0, 256.0);\n"
  114. " vec2 accPoint = texc * size;\n"
  115. " vec2 ip = floor(accPoint);\n"
  116. " vec2 fp = fract(accPoint);\n"
  117. " vec4 inter = textureGather(tex, ip / size, 0);\n"
  118. " vec4 col1 = texture2D(gradient, vec2(inter.x*0.005, 0.0));\n"
  119. " vec4 col2 = texture2D(gradient, vec2(inter.y*0.005, 0.0));\n"
  120. " vec4 col3 = texture2D(gradient, vec2(inter.z*0.005, 0.0));\n"
  121. " vec4 col4 = texture2D(gradient, vec2(inter.w*0.005, 0.0));\n"
  122. " vec4 col = mix(mix(col4, col3, fp.x), mix(col1, col2, fp.x), fp.y);\n"
  123. " gl_FragColor = texture2D(gradient, vec2(v*0.005, 0.0));\n"
  124. " gl_FragColor = col;\n"
  125. // " gl_FragColor = gl_FragColor * texture2D(tex, texc);\n"
  126. // " float v = texture2D(tex, texc).r;\n"
  127. // " gl_FragColor = vec4(v, 1.0 - v, v*v, 1);\n"
  128. // " gl_FragColor.g = 0.3;\n"
  129. "}");
  130. //program.link();
  131. bool bound = program->bind();
  132. int vertexLoc = program->attributeLocation("vertex");
  133. int texCoordsLoc = program->attributeLocation("texCoord");
  134. int colorLocation = program->uniformLocation("color");
  135. int texLoc = program->uniformLocation("tex");
  136. int gradLoc = program->uniformLocation("gradient");
  137. int gradientScaler = program->uniformLocation("gradientScaler");
  138. unsigned char pix[] = { 255, 0, 0, 0, 255, 0, 0, 0, 255 };
  139. GLuint id;
  140. gl.glEnable(GL_TEXTURE_2D);
  141. gl.glGenTextures(1, &id);
  142. gl.glBindTexture(GL_TEXTURE_2D, id);
  143. gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 3, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<char*> (pix));
  144. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  145. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  146. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  147. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  148. gl.glBindTexture(GL_TEXTURE_2D, 0);
  149. gradientTextureId = id;
  150. //gl3.glBindSampler(0, id);
  151. }
  152. void EscapeTimeVisualWidget::resizeGL(int w, int h)
  153. {
  154. auto& gl = *this->context()->functions();
  155. float pixelRatio = this->devicePixelRatioF();
  156. //pixelRatio = 1.0 / 32;
  157. float newW = w * pixelRatio;
  158. float newH = h * pixelRatio;
  159. setResolutionX(newW);
  160. setResolutionY(newH);
  161. gl.glViewport(0, 0, newW, newH);
  162. QMatrix4x4 pmvMatrix;
  163. pmvMatrix.ortho(QRectF{ 0, 0, newW, newH });
  164. int matrixLocation = program->uniformLocation("matrix");
  165. program->setUniformValue(matrixLocation, pmvMatrix);
  166. }
  167. void EscapeTimeVisualWidget::paintGL(void)
  168. {
  169. if (gradientNeedsUpdate)
  170. updateGradient();
  171. /*ETVImage etvi{ *this };
  172. auto& gl = *this->context()->functions();
  173. gl.glClearColor(0.0, 0.2, 0.0, 1.0);
  174. gl.glClear(GL_COLOR_BUFFER_BIT);
  175. etvi.draw(100, 100, 700, 700);*/
  176. }
  177. void EscapeTimeVisualWidget::updateGradient(void)
  178. {
  179. auto& gl = *this->context()->functions();
  180. const int len = 512;
  181. std::unique_ptr<uint8_t[]> pixels = std::make_unique<uint8_t[]>(len * 3);
  182. for (int i = 0; i < len; i++) {
  183. RGBColor c = gradient.get(gradient.getMax() * i / len);
  184. pixels[i * 3] = c.r;
  185. pixels[i * 3 + 1] = c.g;
  186. pixels[i * 3 + 2] = c.b;
  187. }
  188. gl.glEnable(GL_TEXTURE_2D);
  189. gl.glBindTexture(GL_TEXTURE_2D, gradientTextureId);
  190. gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, len, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<unsigned char*> (pixels.get()));
  191. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  192. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  193. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  194. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  195. gl.glBindTexture(GL_TEXTURE_2D, 0);
  196. gradientNeedsUpdate = false;
  197. }
  198. void EscapeTimeVisualWidget::setResolutionX(int w)
  199. {
  200. resolutionX = w;
  201. }
  202. void EscapeTimeVisualWidget::setResolutionY(int h)
  203. {
  204. resolutionY = h;
  205. }
  206. int EscapeTimeVisualWidget::getResolutionX(void) const
  207. {
  208. return resolutionX;
  209. }
  210. int EscapeTimeVisualWidget::getResolutionY(void) const
  211. {
  212. return resolutionY;
  213. }