void DriftingGratingStimulus::drawFrame(shared_ptr<StimulusDisplay> display) { glPushMatrix(); glTranslatef(xoffset->getValue().getFloat(), yoffset->getValue().getFloat(), 0); glRotatef(rotation->getValue().getFloat(),0,0,1); GLfloat scale_size = MAX(width->getValue().getFloat(), height->getValue().getFloat()); glScalef(scale_size, scale_size, 1.0); // scale it up // ---------------------------------------- // GRATING // ---------------------------------------- glDisable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB); // Associate with texture 0 glEnable(GL_TEXTURE_1D); // select our current texture glBindTexture( GL_TEXTURE_1D, grating_textures[display->getCurrentContextIndex()] ); // select modulate to mix texture with color for shading glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); // when texture area is small, bilinear filter the closest mipmap glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); // when texture area is large, bilinear filter the first mipmap glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); // if wrap is true, the texture wraps over at the edges (repeat) // ... false, the texture ends at the edges (clamp) glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glEnable(GL_TEXTURE_1D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(1,1,1,1); // ---------------------------------------- // MASK // ---------------------------------------- glActiveTextureARB(GL_TEXTURE1_ARB); // associate with TEXTURE1_ARB glEnable(GL_TEXTURE_2D); // select our current texture glBindTexture( GL_TEXTURE_2D, mask_textures[display->getCurrentContextIndex()] ); // select modulate to mix texture with color for shading glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); // ---------------------------------------- // DRAW THE QUAD // ---------------------------------------- glBegin(GL_QUADS); MWTime elapsed_time = getElapsedTime(); // here's the description of this equation // starting_phase is in degrees -> degrees*pi/180 = radians // // speed is in degrees/second // spatial_frequency is in cycles/degree // elapsed_time is time since the start the 'play' in us // us/100000 = seconds // // degrees cycles 1 second pi radians // ------- * ------ * ---------- * ----------- * us = radians of phase // s degree 1000000 us 180 degrees // // multiply by -1 so it the grating goes in the correct direction double elapsed_seconds = (double)elapsed_time / (double)1000000; const double phase = -1*(starting_phase->getValue().getFloat()*(M_PI/180.) + speed->getValue().getFloat()*spatial_frequency->getValue().getFloat()*(2.*M_PI)*elapsed_seconds); const double direction_in_radians = direction_in_degrees->getValue().getFloat()*(M_PI/180.); const double aspect = width->getValue().getFloat()/height->getValue().getFloat(); //mprintf("drifting grating draw (%lld - %lld = %lld, %g, %g, %g, %g)", now, start_time, elapsed_time, elapsed_seconds, phase, direction_in_radians, aspect); const float f = cos(direction_in_radians); const float g = sin(direction_in_radians); const float d = ((f+g)-1)/2; const float texture_bl = 0-d; const float texture_br = texture_bl+f; const float texture_tr = 1+d; const float texture_tl = texture_bl+g; const float mask_s_ratio = 1-MIN(1,aspect); const float mask_t_ratio = 1-MIN(1,1/aspect); const float phase_proportion = phase/(2*M_PI); const float cycle_proportion = spatial_frequency->getValue().getFloat()*width->getValue().getFloat(); glNormal3f(0.0, 0.0, 1.0); glMultiTexCoord1fARB(GL_TEXTURE0_ARB, (cycle_proportion*texture_bl)+phase_proportion); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0-mask_s_ratio, 0-mask_t_ratio); glVertex3f(-0.5,-0.5,0); glMultiTexCoord1fARB(GL_TEXTURE0_ARB, (cycle_proportion*texture_br)+phase_proportion); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1+mask_s_ratio, 0-mask_t_ratio); glVertex3f(0.5,-0.5,0); glMultiTexCoord1fARB(GL_TEXTURE0_ARB, (cycle_proportion*texture_tr)+phase_proportion); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1+mask_s_ratio, 1+mask_t_ratio); glVertex3f(0.5,0.5,0); glMultiTexCoord1fARB(GL_TEXTURE0_ARB, (cycle_proportion*texture_tl)+phase_proportion); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0-mask_s_ratio, 1+mask_t_ratio); glVertex3f(-0.5,0.5,0); glEnd(); // GL_QUADS last_phase = phase*(180/M_PI); // ---------------------------------------- // CLEAN-UP // ---------------------------------------- // Unbind grating texture glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture( GL_TEXTURE_1D, 0 ); glDisable(GL_TEXTURE_1D); // Unbind mask texture glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture( GL_TEXTURE_2D, 0 ); glDisable(GL_TEXTURE_2D); glActiveTextureARB(0); // // If alpha_multiplier is less than 1, draw another polygon on top to reduce contrast // float tB = alpha_multiplier->getValue().getFloat(); if ((tB < 1.0f) && (tB >= 0.0f)) { glBegin(GL_QUADS); glColor4f(0.5,0.5,0.5,1-tB); // MH 100730 I believe all grating types have mean 0.5 hardcoded now, fade to 0.5 glVertex3f(-0.5,-0.5,0); glVertex3f(0.5,-0.5,0); glVertex3f(0.5,0.5,0); glVertex3f(-0.5,0.5,0); glEnd(); // GL_QUADS } glPopMatrix(); }
void __stdcall glMultiTexCoord1f(GLenum target, GLfloat s) { if (!ARB_multitexture) return; glMultiTexCoord1fARB(target, s); }