EscapeTimeVisualWidget.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. #include "EscapeTimeVisualWidget.h"
  2. #include "Bitmap.h"
  3. #include <QOpenGLShaderProgram>
  4. #include <QOpenGLContext>
  5. #include <QOpenGLFunctions>
  6. #include <QOpenGLExtraFunctions>
  7. #include <QOpenGLFunctions_3_0>
  8. #include <QOpenGLFunctions_4_0_Core>
  9. #include <vector>
  10. using alm::Gradient;
  11. ETVImage::ETVImage(EscapeTimeVisualWidget& owner,
  12. const Bitmap<float>& img) :
  13. ETVImage{ owner, owner.context(), img }
  14. {
  15. }
  16. ETVImage::ETVImage(EscapeTimeVisualWidget& owner,
  17. QOpenGLContext* context,
  18. const Bitmap<float>& img) :
  19. owner{ owner }
  20. {
  21. auto& gl = *context->functions();
  22. gl.glGenTextures(1, &textureId);
  23. gl.glActiveTexture(GL_TEXTURE0);
  24. gl.glBindTexture(GL_TEXTURE_2D, textureId);
  25. // workaround to weird bug appearing on OS X that the first time
  26. // a texture is displayed, it seems to display arbitrary graphics data
  27. // (e.g. parts of other windows or even old mandelbrot textures)
  28. //
  29. // bug doesn't appear if glTexImage2D is called twice with the image data
  30. #ifdef __APPLE__
  31. gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, int(img.width), int(img.height), 0, GL_RED, GL_FLOAT, img.pixels.get());
  32. #endif // __APPLE__
  33. gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, int(img.width), int(img.height), 0, GL_RED, GL_FLOAT, img.pixels.get());
  34. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  35. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  36. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  37. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  38. gl.glBindTexture(GL_TEXTURE_2D, 0);
  39. }
  40. ETVImage::~ETVImage(void)
  41. {
  42. auto& gl = *owner.context()->functions();
  43. gl.glDeleteTextures(1, &textureId);
  44. }
  45. void ETVImage::draw(float x, float y, float w, float h,
  46. float tx, float ty, float tw, float th)
  47. {
  48. auto& gl = *owner.context()->functions();
  49. auto& gle = *owner.context()->extraFunctions();
  50. GLfloat const fbVertices[] = {
  51. 0, 0, 0.0f,
  52. 0, 256, 0.0f,
  53. 256, 0, 0.0f,
  54. 256, 256, 0.0f,
  55. };
  56. GLfloat const vertices[] = {
  57. x, y, 0.0f,
  58. x, y + h, 0.0f,
  59. x + w, y, 0.0f,
  60. x + w, y + h, 0.0f,
  61. };
  62. GLfloat const texCoords[] = {
  63. tx, ty,
  64. tx, ty + th,
  65. tx + tw, ty,
  66. tx + tw, ty + th,
  67. };
  68. GLfloat const fullTexCoords[] = {
  69. 0, 0,
  70. 0, 1,
  71. 1, 0,
  72. 1, 1,
  73. };
  74. QColor color{ 255, 255, 255 };
  75. auto& program = owner.program;
  76. program->bind();
  77. int vertexLoc = program->attributeLocation("vertex");
  78. int texCoordsLoc = program->attributeLocation("texCoord");
  79. int colorLocation = program->uniformLocation("color");
  80. int texLoc = program->uniformLocation("tex");
  81. int gradLoc = program->uniformLocation("gradient");
  82. int gradientScaler = program->uniformLocation("gradientScaler");
  83. int maxIterations = program->uniformLocation("maxIterations");
  84. program->setAttributeArray(vertexLoc, vertices, 3);
  85. program->setAttributeArray(texCoordsLoc, texCoords, 2);
  86. program->enableAttributeArray(vertexLoc);
  87. program->enableAttributeArray(texCoordsLoc);
  88. program->setUniformValue(colorLocation, color);
  89. program->setUniformValue(gradientScaler, 1.0f / float(owner.gradientTextureMax));
  90. program->setUniformValue(maxIterations, float(owner.maxIterations));
  91. QMatrix4x4 pmvMatrix;
  92. pmvMatrix.ortho(QRect{ 0, 0, owner.getResolutionX(), owner.getResolutionY() });
  93. int matrixLocation = program->uniformLocation("matrix");
  94. program->setUniformValue(matrixLocation, pmvMatrix);
  95. gl.glEnable(GL_TEXTURE_2D);
  96. //GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
  97. //gle.glDrawBuffers(1, drawBuffers);
  98. gl.glBindFramebuffer(GL_FRAMEBUFFER, owner.tileFramebuffer);
  99. gl.glDisable(GL_DEPTH_TEST);
  100. if(gl.glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
  101. printf("error intitializing framebuffer\n");
  102. }
  103. gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, owner.tileTexture, 0);
  104. //gl.glViewport(0, 0, 256, 256);
  105. gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
  106. gl.glUniform1i(texLoc, 0);
  107. gl.glUniform1i(gradLoc, 2);
  108. gl.glActiveTexture(GL_TEXTURE0);
  109. gl.glBindTexture(GL_TEXTURE_2D, textureId);
  110. gl.glActiveTexture(GL_TEXTURE2);
  111. gl.glBindTexture(GL_TEXTURE_2D, owner.gradientTextureId);
  112. gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  113. program->disableAttributeArray(vertexLoc);
  114. program->disableAttributeArray(texCoordsLoc);
  115. /*owner.renderTextures->bind();
  116. gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
  117. //gl.glViewport(0, 0, owner.getResolutionX(), owner.getResolutionY());
  118. int rtVertexLoc = owner.renderTextures->attributeLocation("vertex");
  119. int rtTexCoordsLoc = owner.renderTextures->attributeLocation("texCoord");
  120. int rtTexLoc = owner.renderTextures->attributeLocation("tex");
  121. gl.glActiveTexture(GL_TEXTURE0);
  122. gl.glUniform1i(rtTexLoc, 0);
  123. owner.renderTextures->setAttributeArray(rtVertexLoc, vertices, 3);
  124. owner.renderTextures->setAttributeArray(rtTexCoordsLoc, fullTexCoords, 2);
  125. owner.renderTextures->enableAttributeArray(rtVertexLoc);
  126. owner.renderTextures->enableAttributeArray(rtTexCoordsLoc);
  127. gl.glBindTexture(GL_TEXTURE_2D, owner.tileTexture);
  128. //if (rand() % 2)
  129. //gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  130. owner.renderTextures->disableAttributeArray(rtVertexLoc);
  131. owner.renderTextures->disableAttributeArray(rtTexCoordsLoc);
  132. */
  133. gl.glActiveTexture(GL_TEXTURE0);
  134. }
  135. bool RenderTextureProgram::link(void)
  136. {
  137. QOpenGLShaderProgram::link();
  138. bool bound = this->bind();
  139. vertexLoc = this->attributeLocation("vertex");
  140. texCoordsLoc = this->attributeLocation("texCoord");
  141. colorLocation = this->uniformLocation("color");
  142. texLoc = this->uniformLocation("tex");
  143. gradLoc = this->uniformLocation("gradient");
  144. gradientScalerLoc = this->uniformLocation("gradientScaler");
  145. maxIterationsLoc = this->uniformLocation("maxIterations");
  146. return bound;
  147. }
  148. EscapeTimeVisualWidget::EscapeTimeVisualWidget(QWidget* parent) :
  149. QOpenGLWidget{ parent },
  150. gradientTextureId{ 0 },
  151. gradientTextureMax{ 1.0f },
  152. gradientNeedsUpdate{ false }
  153. {
  154. }
  155. void EscapeTimeVisualWidget::setGradient(Gradient newGradient)
  156. {
  157. this->gradient = newGradient;
  158. gradientNeedsUpdate = true;
  159. update();
  160. }
  161. const Gradient& EscapeTimeVisualWidget::getGradient(void)
  162. {
  163. return gradient;
  164. }
  165. void EscapeTimeVisualWidget::initializeGL(void)
  166. {
  167. auto& gl = *this->context()->functions();
  168. gl.glClearColor(0, 0, 0, 0);
  169. gl.glDisable(GL_DEPTH_TEST);
  170. fprintf(stdout, "version: %s\n", gl.glGetString(GL_VERSION));
  171. fflush(stdout);
  172. //glShadeModel(GL_SMOOTH);
  173. renderTextures = new QOpenGLShaderProgram{ this->context() };
  174. renderTextures->addShaderFromSourceCode(QOpenGLShader::Vertex,
  175. "attribute highp vec4 vertex;\n"
  176. "attribute highp vec2 texCoord;\n"
  177. "uniform highp mat4 matrix;\n"
  178. "varying highp vec2 texc;\n"
  179. "void main(void)\n"
  180. "{\n"
  181. " gl_Position = matrix * vertex;\n"
  182. " texc = texCoord;\n"
  183. "}");
  184. renderTextures->addShaderFromSourceCode(QOpenGLShader::Fragment,
  185. // "#version 110\n"
  186. "uniform sampler2D tex;\n"
  187. "varying highp vec2 texc;\n"
  188. "void main(void)\n"
  189. "{\n"
  190. " gl_FragColor = texture2D(tex, texc);\n"
  191. "}");
  192. renderTextures->link();
  193. juliaPreviewer = new QOpenGLShaderProgram{ this->context() };
  194. juliaPreviewer->addShaderFromSourceCode(QOpenGLShader::Vertex,
  195. "attribute highp vec4 vertex;\n"
  196. "attribute highp vec2 texCoord;\n"
  197. "uniform highp mat4 matrix;\n"
  198. "varying highp vec2 texc;\n"
  199. "void main(void)\n"
  200. "{\n"
  201. " gl_Position = matrix * vertex;\n"
  202. " texc = texCoord;\n"
  203. "}");
  204. juliaPreviewer->addShaderFromSourceCode(QOpenGLShader::Fragment,
  205. // "#version 110\n"
  206. "uniform sampler2D gradient;\n"
  207. "uniform highp float gradientScaler;\n"
  208. "const highp float maxIterations = 350.0;\n"
  209. "varying highp vec2 texc;\n"
  210. "uniform highp float juliaX;\n"
  211. "uniform highp float juliaY;\n"
  212. "uniform int smoothB;\n"
  213. "const highp float left = -1.5;\n"
  214. "const highp float right = 1.5;\n"
  215. "const highp float top = -1.5;\n"
  216. "const highp float bottom = 1.5;\n"
  217. "highp float map(highp float a, highp float b, highp float v) {\n"
  218. " return (1.0 - v) * a + b * v;\n"
  219. "}\n"
  220. "highp float iterate(highp float x, highp float y, highp float ca, highp float cb) {\n"
  221. " int k = 0;\n"
  222. " highp float a = x;\n"
  223. " highp float b = y;\n"
  224. " while(k <= int(maxIterations)) {\n"
  225. " highp float aa = a * a;\n"
  226. " highp float bb = b * b;\n"
  227. " highp float abab = 2.0 * a * b;\n"
  228. " a = aa - bb + ca;\n"
  229. " b = abab + cb;\n"
  230. " if (aa + bb >= 16.0) break;\n"
  231. " k = k + 1;\n"
  232. " }\n"
  233. " if (smoothB != 0) {\n"
  234. " return float(k) + 1.0 - log2(log(a * a + b * b) * 0.5);\n"
  235. " } else {\n"
  236. " return float(k);\n"
  237. " }\n"
  238. "}\n"
  239. "void main(void)\n"
  240. "{\n"
  241. " highp float x = map(left, right, texc.x);\n"
  242. " highp float y = map(top, bottom, texc.y);\n"
  243. " highp float v = iterate(x, y, juliaX, juliaY);\n"
  244. " if (v >= maxIterations) {\n"
  245. " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
  246. " } else {\n"
  247. " highp float vnorm = v * gradientScaler;\n"
  248. " gl_FragColor = texture2D(gradient, vec2(vnorm, 0.0));\n"
  249. " }\n"
  250. "}");
  251. juliaPreviewer->link();
  252. program = new QOpenGLShaderProgram{ this->context() };
  253. bool vert = program->addShaderFromSourceCode(QOpenGLShader::Vertex,
  254. "attribute highp vec4 vertex;\n"
  255. "attribute highp vec2 texCoord;\n"
  256. "uniform highp mat4 matrix;\n"
  257. "varying highp vec2 texc;\n"
  258. "void main(void)\n"
  259. "{\n"
  260. " gl_Position = matrix * vertex;\n"
  261. " texc = texCoord;\n"
  262. "}");
  263. // TODO rewrite this monster
  264. // remove hardcoded 256 texture size
  265. if (!context()->isOpenGLES() &&
  266. context()->versionFunctions<QOpenGLFunctions_4_0_Core>() != nullptr) {
  267. bool frag = program->addShaderFromSourceCode(QOpenGLShader::Fragment,
  268. "#version 400\n"
  269. "uniform sampler2D gradient;\n"
  270. "uniform sampler2D tex;\n"
  271. "uniform mediump vec4 color;\n"
  272. "uniform highp float gradientScaler;\n"
  273. "uniform highp float maxIterations;\n"
  274. "varying highp vec2 texc;\n"
  275. "vec4 colorize(float pos) {\n"
  276. " if (pos >= maxIterations) {\n"
  277. " return vec4(0.0, 0.0, 0.0, 1.0);\n"
  278. " } else {\n"
  279. " return texture2D(gradient, vec2(pos * gradientScaler, 0.0));\n"
  280. " }\n"
  281. "}\n"
  282. "void main(void)\n"
  283. "{\n"
  284. " vec2 size = textureSize(tex, 0);\n"
  285. " size = vec2(256.0, 256.0);\n"
  286. " vec2 accPoint = texc * size;\n"
  287. " vec2 ip = floor(accPoint + 0.5);\n"
  288. " vec2 fp = fract(accPoint + 0.5);\n"
  289. " vec4 inter = textureGather(tex, ip / size, 0);\n"
  290. " vec4 col1 = colorize(inter.x);\n"
  291. " vec4 col2 = colorize(inter.y);\n"
  292. " vec4 col3 = colorize(inter.z);\n"
  293. " vec4 col4 = colorize(inter.w);\n"
  294. " vec4 col = mix(mix(col4, col3, fp.x), mix(col1, col2, fp.x), fp.y);\n"
  295. " gl_FragColor = col;\n"
  296. // " gl_FragColor = gl_FragColor * texture2D(tex, texc);\n"
  297. // " float v = texture2D(tex, texc).r;\n"
  298. // " gl_FragColor = vec4(v, 1.0 - v, v*v, 1);\n"
  299. // " gl_FragColor.g = 0.3;\n"
  300. "}");
  301. }
  302. else {
  303. bool frag = program->addShaderFromSourceCode(QOpenGLShader::Fragment,
  304. // "#version 110\n"
  305. "uniform sampler2D gradient;\n"
  306. "uniform sampler2D tex;\n"
  307. "uniform mediump vec4 color;\n"
  308. "uniform highp float gradientScaler;\n"
  309. "uniform highp float maxIterations;\n"
  310. "varying highp vec2 texc;\n"
  311. "void main(void)\n"
  312. "{\n"
  313. " highp float v = texture2D(tex, texc).r;\n"
  314. " if (v >= maxIterations) {\n"
  315. " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
  316. " } else {\n"
  317. " gl_FragColor = texture2D(gradient, vec2(v * gradientScaler, 0.0));\n"
  318. " }\n"
  319. // " gl_FragColor = gl_FragColor * texture2D(tex, texc);\n"
  320. // " float v = texture2D(tex, texc).r;\n"
  321. // " gl_FragColor = vec4(v, 1.0 - v, v*v, 1);\n"
  322. // " gl_FragColor.g = 0.3;\n"
  323. "}");
  324. }
  325. //program.link();
  326. bool bound = program->bind();
  327. bound = renderTextures->bind();
  328. int vertexLoc = program->attributeLocation("vertex");
  329. int texCoordsLoc = program->attributeLocation("texCoord");
  330. int colorLocation = program->uniformLocation("color");
  331. int texLoc = program->uniformLocation("tex");
  332. int gradLoc = program->uniformLocation("gradient");
  333. int gradientScaler = program->uniformLocation("gradientScaler");
  334. int maxIterations = program->uniformLocation("maxIterations");
  335. program->setUniformValue(gradientScaler, 0.005f);
  336. program->setUniformValue(maxIterations, 250.0f);
  337. auto& gle = *this->context()->extraFunctions();
  338. gl.glGenTextures(1, &tileTexture);
  339. gl.glBindTexture(GL_TEXTURE_2D, tileTexture);
  340. gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
  341. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  342. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  343. gl.glBindTexture(GL_TEXTURE_2D, 0);
  344. gl.glGenFramebuffers(1, &tileFramebuffer);
  345. gl.glBindFramebuffer(GL_FRAMEBUFFER, tileFramebuffer);
  346. gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tileTexture, 0);
  347. GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
  348. gle.glDrawBuffers(1, drawBuffers);
  349. if(gl.glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
  350. printf("error intitializing framebuffer\n");
  351. }
  352. gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
  353. unsigned char pix[] = { 255, 0, 0, 0, 255, 0, 0, 0, 255 };
  354. updateGradient();
  355. gl.glDisable(GL_DEPTH_TEST);
  356. //gl3.glBindSampler(0, id);
  357. }
  358. void EscapeTimeVisualWidget::resizeGL(int w, int h)
  359. {
  360. auto& gl = *this->context()->functions();
  361. float pixelRatio = this->devicePixelRatioF();
  362. //pixelRatio = 1.0 / 32;
  363. float newW = w * pixelRatio;
  364. float newH = h * pixelRatio;
  365. setResolutionX(newW);
  366. setResolutionY(newH);
  367. gl.glViewport(0, 0, newW, newH);
  368. QMatrix4x4 pmvMatrix;
  369. pmvMatrix.ortho(QRectF{ 0, 0, newW, newH });
  370. int matrixLocation = program->uniformLocation("matrix");
  371. int rtMatrixLocation = renderTextures->uniformLocation("matrix");
  372. int jMatrixLocation = juliaPreviewer->uniformLocation("matrix");
  373. program->setUniformValue(matrixLocation, pmvMatrix);
  374. renderTextures->setUniformValue(rtMatrixLocation, pmvMatrix);
  375. juliaPreviewer->setUniformValue(jMatrixLocation, pmvMatrix);
  376. }
  377. void EscapeTimeVisualWidget::paintGL(void)
  378. {
  379. if (gradientNeedsUpdate)
  380. updateGradient();
  381. /*ETVImage etvi{ *this };
  382. auto& gl = *this->context()->functions();
  383. gl.glClearColor(0.0, 0.2, 0.0, 1.0);
  384. gl.glClear(GL_COLOR_BUFFER_BIT);
  385. etvi.draw(100, 100, 700, 700);*/
  386. }
  387. void EscapeTimeVisualWidget::drawJulia(float jx, float jy, QRectF area, bool drawSmooth)
  388. {
  389. juliaPreviewer->bind();
  390. int gradLoc = juliaPreviewer->uniformLocation("gradient");
  391. int gradientScaler = juliaPreviewer->uniformLocation("gradientScaler");
  392. int juliaX = juliaPreviewer->uniformLocation("juliaX");
  393. int juliaY = juliaPreviewer->uniformLocation("juliaY");
  394. int vertexLoc = juliaPreviewer->attributeLocation("vertex");
  395. int texCoordsLoc = juliaPreviewer->attributeLocation("texCoord");
  396. int maxIterLoc = juliaPreviewer->attributeLocation("maxIterations");
  397. int smooth = juliaPreviewer->uniformLocation("smoothB");
  398. int matrixLocation = juliaPreviewer->uniformLocation("matrix");
  399. QMatrix4x4 pmvMatrix;
  400. pmvMatrix.ortho(QRect{ 0, 0, getResolutionX(), getResolutionY() });
  401. juliaPreviewer->setUniformValue(matrixLocation, pmvMatrix);
  402. const float x = area.x();
  403. const float y = area.y();
  404. const float w = area.width();
  405. const float h = area.height();
  406. GLfloat const vertices[] = {
  407. x, y, 0.0f,
  408. x, y + h, 0.0f,
  409. x + w, y, 0.0f,
  410. x + w, y + h, 0.0f,
  411. };
  412. GLfloat const texCoords[] = {
  413. 0, 0,
  414. 0, 1,
  415. 1, 0,
  416. 1, 1,
  417. };
  418. auto& gl = *this->context()->functions();
  419. gl.glEnable(GL_TEXTURE_2D);
  420. gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
  421. juliaPreviewer->setAttributeArray(vertexLoc, vertices, 3);
  422. juliaPreviewer->setAttributeArray(texCoordsLoc, texCoords, 2);
  423. juliaPreviewer->enableAttributeArray(vertexLoc);
  424. juliaPreviewer->enableAttributeArray(texCoordsLoc);
  425. juliaPreviewer->setUniformValue(gradientScaler, 1.0f / float(gradientTextureMax));
  426. juliaPreviewer->setUniformValue(maxIterLoc, float(250));
  427. juliaPreviewer->setUniformValue(juliaX, float(jx));
  428. juliaPreviewer->setUniformValue(juliaY, float(jy));
  429. juliaPreviewer->setUniformValue(smooth, int(drawSmooth ? 1 : 0));
  430. gl.glUniform1i(gradLoc, 0);
  431. gl.glActiveTexture(GL_TEXTURE0);
  432. gl.glBindTexture(GL_TEXTURE_2D, gradientTextureId);
  433. gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  434. juliaPreviewer->disableAttributeArray(vertexLoc);
  435. juliaPreviewer->disableAttributeArray(texCoordsLoc);
  436. //juliaPreviewer->release();
  437. //program->bind();
  438. }
  439. void EscapeTimeVisualWidget::setMaxIterationCutoff(float maxIter)
  440. {
  441. this->maxIterations = maxIter;
  442. }
  443. void EscapeTimeVisualWidget::updateGradient(void)
  444. {
  445. auto& gl = *this->context()->functions();
  446. int len = 512;
  447. if (gradient.getPoints().size() > 25) {
  448. len = 2048;
  449. }
  450. else if (gradient.getPoints().size() > 7) {
  451. len = 1024;
  452. }
  453. std::unique_ptr<uint8_t[]> pixels = std::make_unique<uint8_t[]>(len * 3);
  454. for (int i = 0; i < len; i++) {
  455. RGBColor c = gradient.get(gradient.getMax() * i / len);
  456. pixels[i * 3] = c.r;
  457. pixels[i * 3 + 1] = c.g;
  458. pixels[i * 3 + 2] = c.b;
  459. }
  460. gl.glEnable(GL_TEXTURE_2D);
  461. if (gradientTextureId == 0)
  462. gl.glGenTextures(1, &gradientTextureId);
  463. gl.glBindTexture(GL_TEXTURE_2D, gradientTextureId);
  464. gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, len, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<unsigned char*> (pixels.get()));
  465. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  466. if (gradient.isRepeat())
  467. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  468. else
  469. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  470. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  471. gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  472. gl.glBindTexture(GL_TEXTURE_2D, 0);
  473. this->gradientTextureMax = gradient.getMax();
  474. gradientNeedsUpdate = false;
  475. }
  476. void EscapeTimeVisualWidget::setResolutionX(int w)
  477. {
  478. resolutionX = w;
  479. }
  480. void EscapeTimeVisualWidget::setResolutionY(int h)
  481. {
  482. resolutionY = h;
  483. }
  484. int EscapeTimeVisualWidget::getResolutionX(void) const
  485. {
  486. return resolutionX;
  487. }
  488. int EscapeTimeVisualWidget::getResolutionY(void) const
  489. {
  490. return resolutionY;
  491. }