void GemShape :: SetVertex(GemState* state,float x, float y, float z, float s, float t, float r, float q, int curCoord) { int numCoords = 0; int numUnits = 0; state->get(GemState::_GL_TEX_NUMCOORDS, numCoords); state->get(GemState::_GL_TEX_UNITS, numUnits); if (numCoords) { s*=state->texCoordX(curCoord); t*=state->texCoordY(curCoord); } if (numUnits) { for(int i=0; i<numUnits; i++) { glMultiTexCoord4fARB(GL_TEXTURE0+i, s, t, r, q); } } else { // no multitexturing! glTexCoord4f(s, t, r, q); } glVertex3f( x, y, z ); }
/* GL locking is done by the caller */ static void drawStridedSlow(IWineD3DDevice *iface, const struct wined3d_context *context, const struct wined3d_stream_info *si, UINT NumVertexes, GLenum glPrimType, const void *idxData, UINT idxSize, UINT startIdx) { unsigned int textureNo = 0; const WORD *pIdxBufS = NULL; const DWORD *pIdxBufL = NULL; UINT vx_index; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; const UINT *streamOffset = This->stateBlock->streamOffset; long SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex; BOOL pixelShader = use_ps(This->stateBlock); BOOL specular_fog = FALSE; const BYTE *texCoords[WINED3DDP_MAXTEXCOORD]; const BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL; const struct wined3d_gl_info *gl_info = context->gl_info; UINT texture_stages = gl_info->limits.texture_stages; const struct wined3d_stream_info_element *element; UINT num_untracked_materials; DWORD tex_mask = 0; TRACE("Using slow vertex array code\n"); /* Variable Initialization */ if (idxSize != 0) { /* Immediate mode drawing can't make use of indices in a vbo - get the data from the index buffer. * If the index buffer has no vbo(not supported or other reason), or with user pointer drawing * idxData will be != NULL */ if(idxData == NULL) { idxData = buffer_get_sysmem((struct wined3d_buffer *) This->stateBlock->pIndexData); } if (idxSize == 2) pIdxBufS = idxData; else pIdxBufL = idxData; } else if (idxData) { ERR("non-NULL idxData with 0 idxSize, this should never happen\n"); return; } /* Start drawing in GL */ glBegin(glPrimType); if (si->use_map & (1 << WINED3D_FFP_POSITION)) { element = &si->elements[WINED3D_FFP_POSITION]; position = element->data + streamOffset[element->stream_idx]; } if (si->use_map & (1 << WINED3D_FFP_NORMAL)) { element = &si->elements[WINED3D_FFP_NORMAL]; normal = element->data + streamOffset[element->stream_idx]; } else { glNormal3f(0, 0, 0); } num_untracked_materials = context->num_untracked_materials; if (si->use_map & (1 << WINED3D_FFP_DIFFUSE)) { element = &si->elements[WINED3D_FFP_DIFFUSE]; diffuse = element->data + streamOffset[element->stream_idx]; if (num_untracked_materials && element->format_desc->format != WINED3DFMT_B8G8R8A8_UNORM) FIXME("Implement diffuse color tracking from %s\n", debug_d3dformat(element->format_desc->format)); } else { glColor4f(1.0f, 1.0f, 1.0f, 1.0f); } if (si->use_map & (1 << WINED3D_FFP_SPECULAR)) { element = &si->elements[WINED3D_FFP_SPECULAR]; specular = element->data + streamOffset[element->stream_idx]; /* special case where the fog density is stored in the specular alpha channel */ if (This->stateBlock->renderState[WINED3DRS_FOGENABLE] && (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || si->elements[WINED3D_FFP_POSITION].format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT) && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) { if (gl_info->supported[EXT_FOG_COORD]) { if (element->format_desc->format == WINED3DFMT_B8G8R8A8_UNORM) specular_fog = TRUE; else FIXME("Implement fog coordinates from %s\n", debug_d3dformat(element->format_desc->format)); } else { static BOOL warned; if (!warned) { /* TODO: Use the fog table code from old ddraw */ FIXME("Implement fog for transformed vertices in software\n"); warned = TRUE; } } } } else if (gl_info->supported[EXT_SECONDARY_COLOR]) { GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0); } for (textureNo = 0; textureNo < texture_stages; ++textureNo) { int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX]; DWORD texture_idx = This->texUnitMap[textureNo]; if (!gl_info->supported[ARB_MULTITEXTURE] && textureNo > 0) { FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); continue; } if (!pixelShader && !This->stateBlock->textures[textureNo]) continue; if (texture_idx == WINED3D_UNMAPPED_STAGE) continue; if (coordIdx > 7) { TRACE("tex: %d - Skip tex coords, as being system generated\n", textureNo); continue; } else if (coordIdx < 0) { FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx); continue; } if (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))) { element = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx]; texCoords[coordIdx] = element->data + streamOffset[element->stream_idx]; tex_mask |= (1 << textureNo); } else { TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo); if (gl_info->supported[ARB_MULTITEXTURE]) GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1)); else glTexCoord4f(0, 0, 0, 1); } } /* We shouldn't start this function if any VBO is involved. Should I put a safety check here? * Guess it's not necessary(we crash then anyway) and would only eat CPU time */ /* For each primitive */ for (vx_index = 0; vx_index < NumVertexes; ++vx_index) { UINT texture, tmp_tex_mask; /* Blending data and Point sizes are not supported by this function. They are not supported by the fixed * function pipeline at all. A Fixme for them is printed after decoding the vertex declaration */ /* For indexed data, we need to go a few more strides in */ if (idxData != NULL) { /* Indexed so work out the number of strides to skip */ if (idxSize == 2) SkipnStrides = pIdxBufS[startIdx + vx_index] + This->stateBlock->loadBaseVertexIndex; else SkipnStrides = pIdxBufL[startIdx + vx_index] + This->stateBlock->loadBaseVertexIndex; } tmp_tex_mask = tex_mask; for (texture = 0; tmp_tex_mask; tmp_tex_mask >>= 1, ++texture) { int coord_idx; const void *ptr; DWORD texture_idx; if (!(tmp_tex_mask & 1)) continue; coord_idx = This->stateBlock->textureState[texture][WINED3DTSS_TEXCOORDINDEX]; ptr = texCoords[coord_idx] + (SkipnStrides * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride); texture_idx = This->texUnitMap[texture]; multi_texcoord_funcs[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format_desc->emit_idx]( GL_TEXTURE0_ARB + texture_idx, ptr); } /* Diffuse -------------------------------- */ if (diffuse) { const void *ptrToCoords = diffuse + SkipnStrides * si->elements[WINED3D_FFP_DIFFUSE].stride; diffuse_funcs[si->elements[WINED3D_FFP_DIFFUSE].format_desc->emit_idx](ptrToCoords); if (num_untracked_materials) { DWORD diffuseColor = ((const DWORD *)ptrToCoords)[0]; unsigned char i; float color[4]; color[0] = D3DCOLOR_B_R(diffuseColor) / 255.0f; color[1] = D3DCOLOR_B_G(diffuseColor) / 255.0f; color[2] = D3DCOLOR_B_B(diffuseColor) / 255.0f; color[3] = D3DCOLOR_B_A(diffuseColor) / 255.0f; for (i = 0; i < num_untracked_materials; ++i) { glMaterialfv(GL_FRONT_AND_BACK, context->untracked_materials[i], color); } } } /* Specular ------------------------------- */ if (specular) { const void *ptrToCoords = specular + SkipnStrides * si->elements[WINED3D_FFP_SPECULAR].stride; specular_funcs[si->elements[WINED3D_FFP_SPECULAR].format_desc->emit_idx](ptrToCoords); if (specular_fog) { DWORD specularColor = *(const DWORD *)ptrToCoords; GL_EXTCALL(glFogCoordfEXT(specularColor >> 24)); } } /* Normal -------------------------------- */ if (normal != NULL) { const void *ptrToCoords = normal + SkipnStrides * si->elements[WINED3D_FFP_NORMAL].stride; normal_funcs[si->elements[WINED3D_FFP_NORMAL].format_desc->emit_idx](ptrToCoords); } /* Position -------------------------------- */ if (position) { const void *ptrToCoords = position + SkipnStrides * si->elements[WINED3D_FFP_POSITION].stride; position_funcs[si->elements[WINED3D_FFP_POSITION].format_desc->emit_idx](ptrToCoords); } /* For non indexed mode, step onto next parts */ if (idxData == NULL) { ++SkipnStrides; } } glEnd(); checkGLcall("glEnd and previous calls"); }
void __stdcall glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { if (!ARB_multitexture) return; glMultiTexCoord4fARB(target, s, t, r, q); }
// Render a world polygon using multiple TMUs to map the regular texture and lightmap in one pass void Render_WorldPolyMultitexture(DRV_TLVertex *Pnts, int32 NumPoints, geRDriver_THandle *THandle, DRV_LInfo *LInfo, GLfloat shiftU, GLfloat shiftV, GLfloat scaleU, GLfloat scaleV, GLubyte alpha) { DRV_TLVertex *pPnt; GLfloat zRecip; GLfloat tu, tv, lu, lv; GLfloat shiftU2, shiftV2; GLint i; if(LInfo != NULL) { glActiveTextureARB(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); if(boundTexture2 != LInfo->THandle->TextureID) { glBindTexture(GL_TEXTURE_2D, LInfo->THandle->TextureID); boundTexture2 = LInfo->THandle->TextureID; } if(LInfo->THandle->Flags & THANDLE_UPDATE) { THandle_Update(LInfo->THandle); } shiftU2 = (GLfloat)LInfo->MinU - 8.0f; shiftV2 = (GLfloat)LInfo->MinV - 8.0f; } pPnt = Pnts; glBegin(GL_TRIANGLE_FAN); for(i = 0; i < NumPoints; i++) { zRecip = 1.0f / pPnt->z; tu = (pPnt->u * scaleU + shiftU); tv = (pPnt->v * scaleV + shiftV); glColor4ub((GLubyte)pPnt->r, (GLubyte)pPnt->g, (GLubyte)pPnt->b, alpha); glMultiTexCoord4fARB(GL_TEXTURE0_ARB, tu * THandle->InvScale * zRecip, tv * THandle->InvScale * zRecip, 0.0f, zRecip); if(LInfo) { lu = pPnt->u - shiftU2; lv = pPnt->v - shiftV2; glMultiTexCoord4fARB(GL_TEXTURE1_ARB, lu * LInfo->THandle->InvScale * zRecip, lv * LInfo->THandle->InvScale * zRecip, 0.0f, zRecip); } glVertex3f(pPnt->x, pPnt->y, -1.0f + zRecip); pPnt++; } glEnd(); if(LInfo != NULL) { glDisable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB); } }