EscapeTimeVisualWidget.cpp 7.1 KB

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