本节主要讲利用cocos2dx机制实现opengl es shader脚本的绘制

  这里先看下最终效果:

                    

这里分别实现了灰度效果及残影的效果。

一、绘制基类

  这里主要参考了cocos2dx源码中 RenderTexture 的实现,有兴趣的可以了解下。

绘制基类RenderShader主要实现以下方法:

//******************************************************************
// 文件名: RenderShader.h
// 创建人: 稀饭lei
// 版 本: 1.0
// 描 述: 特效基类
//******************************************************************
#ifndef _RenderShader_H__
#define _RenderShader_H__
#include "cocos2d.h"
USING_NS_CC; // GL纹理坐标组
static const GLfloat ccRenderTextcord[] ={
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
class RenderShader : public Node
{
public:
static RenderShader* create(); virtual bool LoadByteArray(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray); //加载 shader文件 void begin(); // 用于设置绘制开始要调用的onBegin void end(); // 用于设置绘制结束要调用的onEnd void push2Draw(Node* node); // 添加待绘制节点 virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override; // cocos2dx绘制回调 protected:
virtual void onBegin(); virtual void onEnd(); //virtual void onClear(); virtual void Render(); // 绘制实现 virtual bool init(); virtual void CreateFrameBuffer(); //创建FBO及texture RenderShader(void); virtual ~RenderShader(void); GLuint m_nFrameBuffer; // 用于当前绘制的fbo GLuint m_nFrameBufferTexture; // 用于绑定在fbo中的texture GLProgram* m_glprogram; // GL绘制管理 GLint m_nOldFBO; // 原来的fbo CustomCommand _beginCommand;
CustomCommand _endCommand;
GroupCommand _groupCommand; std::set<Node*> sRenderChild; // 需要绘制的节点 Size m_sRenderSize;
}; #endif

这里有几个主要实现:

1、我们用push2Draw(Node* node);  方法将待绘制的节点添加到sRenderChild中等待处理。

2、参考RenderTexture 的实现,我们也利用begin,end将需要绘制的节点利用visit访问添加到当前的RenderShader类所在的render层中进行绘制。

3、在实际绘制过程中调用的onBegin中缓存对应的坐标系,同时绑定我们创建的FBO使得visit进来的节点可以绘制到当前FBO中。然后在onEnd中调用render方法将我们的FBO内容绘制原来cocos2dx底层的FBO上。

4、在render()实现如何绘制当前FBO的内容到cocos2dx的FBO上。(实际shader作业的地方)

详细实现代码如下:

#include "RenderShader.h"
#define STRINGIFY(A) #A
const char* ccPositionTextureColor_frag_test = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n varying vec4 v_fragmentColor;
varying vec2 v_texCoord; void main()
{
vec4 color = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(vec3(gray), color.a);
}
); RenderShader* RenderShader::create()
{
auto node = new RenderShader();
if (node && node->init())
{
node->autorelease();
return node;
}
delete node;
return nullptr;
} bool RenderShader::init()
{
if (m_glprogram)
{
m_glprogram->release();
m_glprogram = nullptr;
} CreateFrameBuffer(); m_glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, ccPositionTextureColor_frag_test);
m_glprogram->retain(); return true;
} RenderShader::RenderShader(void)
:m_nFrameBuffer(), m_nFrameBufferTexture(), m_glprogram(nullptr)
{
GLView* glView = Director::getInstance()->getOpenGLView();
if (!glView)
{
return;
}
//屏幕大小
m_sRenderSize = glView->getFrameSize();
} RenderShader::~RenderShader(void)
{
if (m_glprogram)
{
m_glprogram->release();
m_glprogram = nullptr;
}
if (m_nFrameBuffer)
{
glDeleteFramebuffers(, &m_nFrameBuffer);
m_nFrameBuffer = ;
}
if (m_nFrameBufferTexture)
{
glDeleteTextures(, &m_nFrameBufferTexture);
m_nFrameBufferTexture = ;
}
} bool RenderShader::LoadByteArray(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray)
{
if (m_glprogram)
{
m_glprogram->release();
m_glprogram = nullptr;
} this->CreateFrameBuffer(); m_glprogram = GLProgram::createWithByteArrays(vShaderByteArray, fShaderByteArray);
m_glprogram->retain(); return true;
} void RenderShader::onBegin()
{
if (!m_nFrameBuffer)
{
return;
}
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); //save old fbo and bind own
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
} void RenderShader::onEnd()
{
if (!m_nFrameBuffer)
{
return;
} // restore viewport for render to direct fbo
Director *director = Director::getInstance();
// restore viewport
director->setViewport();
this->Render(); glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
} void RenderShader::Render()
{
if (!m_glprogram || !m_nFrameBufferTexture)
{
return;
} glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
m_glprogram->use();
m_glprogram->setUniformsForBuiltins(); //GLuint glTexture = m_glprogram->getUniformLocationForName("CC_Texture0");
//glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, m_nFrameBufferTexture);
//glUniform1i(glTexture, 0);
GL::bindTexture2D(m_nFrameBufferTexture);
Size sSize = Director::getInstance()->getVisibleSize();
float x = ;
float y = ;
float w = sSize.width;
float h = sSize.height;
GLfloat vertices[] = {
x, y + h,
x + w, y + h,
x, y,
x + w, y
}; glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, , GL_FLOAT, GL_FALSE, , ccRenderTextcord); glDrawArrays(GL_TRIANGLE_STRIP, , ); /*GL::bindVAO(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);*/
} void RenderShader::CreateFrameBuffer()
{
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
if (m_nFrameBuffer == )
{
glGenFramebuffers(, &m_nFrameBuffer); if (m_nFrameBuffer == )
{
CCLOG("m_FilterFrameBuffer == 0");
return;
}
}
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer); if (m_nFrameBufferTexture == )
{
glGenTextures(, &m_nFrameBufferTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_nFrameBufferTexture); GLsizei nWidth = m_sRenderSize.width;
GLsizei nHeight = m_sRenderSize.height;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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);
glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, nWidth, nHeight, , GL_RGBA, GL_UNSIGNED_BYTE, );
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
CCLOG("cocos2d: Texture2D: Error uploading compressed texture glError: 0x%04X", err);
return;
} }
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_nFrameBufferTexture, ); GLenum error;
if ((error = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE)
{
CCLOG("Failed to make complete framebuffer object 0x%X", error);
return;
} glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
} void RenderShader::begin()
{
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); _groupCommand.init(_globalZOrder); Renderer *renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID()); _beginCommand.init(_globalZOrder);
_beginCommand.func = CC_CALLBACK_0(RenderShader::onBegin, this); renderer->addCommand(&_beginCommand);
} void RenderShader::end()
{
_endCommand.init(_globalZOrder);
_endCommand.func = CC_CALLBACK_0(RenderShader::onEnd, this); Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack"); Renderer *renderer = director->getRenderer();
renderer->addCommand(&_endCommand);
renderer->popGroup(); director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); } void RenderShader::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
//Begin will create a render group using new render target
begin(); ////clear screen
//_clearCommand.init(_globalZOrder);
//_clearCommand.func = CC_CALLBACK_0(RenderShader::onClear, this);
//renderer->addCommand(&_clearCommand); //! make sure all children are drawn
{
auto it = sRenderChild.begin();
while (it != sRenderChild.end())
{
if (Node* node = *it)
{
node->visit(renderer, transform, flags);
node->release();
}
++it;
}
sRenderChild.clear();
}
//End will pop the current render group
end();
} void RenderShader::push2Draw(Node* node)
{
if (node && sRenderChild.find(node) == sRenderChild.end())
{
node->retain();
sRenderChild.insert(node);
}
else
{
CCLOG(" push same!!!");
}
}

这里shader代码实现的是灰度图的效果,其他效果可以自己修改ccPositionTextureColor_frag_test内容。

二、实际使用

1、将RenderShader当成正常的Node使用,设置父节点及index坐标等。

        m_pShader = RenderShader::create();
this->addChild(m_pShader);

2、因为RenderShader在draw中对需要绘制的子节点进行了清理,所以需要每次重新对子节点进行添加,添加动画节点如下:

void CPlayer::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
if (m_pShader)
{
m_pShader->push2Draw(m_pNode);
}
}

主要事项:RenderShader在Render方法中将内容绘制到原来的FBO中,而cocos2dx对每个需要绘制的同一index层级会在开始的时候单独创建一个FBO来处理。因而如果RenderShader单独一个层级可能导致此时的FBO没有创建,导致没有绘制效果。

到这里我们就实现灰色角色的效果了,使用也依照cocos2dx的用法,相对简单。

三、残影效果扩展

主要实现代码如下:

//******************************************************************
// 文件名: RemindShader.h
// 创建人: 稀饭lei
// 版 本: 1.0
// 描 述: 残影特效
//******************************************************************
#ifndef _RemindShader_H__
#define _RemindShader_H__
#include "RenderShader.h"
USING_NS_CC;
#define REMIND_RENDER_COUNT 5 // 残影个数
class RemindShader :public RenderShader
{
public:
static RemindShader* create(); virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
private:
virtual void onBegin() override; //virtual void onClear(); virtual void Render() override; virtual bool init() override; virtual void CreateFrameBuffer() override; RemindShader(void); virtual ~RemindShader(void); GLuint m_pTextureArr[REMIND_RENDER_COUNT]; int m_nRenderFrq; // 渲染间隔帧率 int m_nRenderCount; // 渲染间隔计数 int m_nCurTexutreIndex; // 当前渲染的纹理ID
}; #endif #include "RemindShader.h" #define STRINGIFY(A) #A
const char* ccRemind_fsh = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n varying vec2 v_texCoord;
uniform float u_alpha; void main()
{
vec4 pcolor = texture2D(CC_Texture0, v_texCoord) * u_alpha;
gl_FragColor = pcolor;
}
); RemindShader* RemindShader::create()
{
auto node = new RemindShader();
if (node && node->init())
{
node->autorelease();
return node;
}
delete node;
return nullptr;
} bool RemindShader::init()
{
if (m_glprogram)
{
m_glprogram->release();
m_glprogram = nullptr;
} CreateFrameBuffer();
m_glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, ccRemind_fsh);
m_glprogram->retain();
return true;
} RemindShader::RemindShader(void)
: m_nCurTexutreIndex(), m_nRenderFrq(), m_nRenderCount()
{
memset(m_pTextureArr, , REMIND_RENDER_COUNT);
} RemindShader::~RemindShader(void)
{
if (m_pTextureArr[])
{
glDeleteTextures(REMIND_RENDER_COUNT, m_pTextureArr);
memset(m_pTextureArr, , REMIND_RENDER_COUNT);
}
} void RemindShader::onBegin()
{
if (!m_nFrameBuffer)
{
return;
}
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
// director->setProjection(director->getProjection());
// GLView* glView = director->getOpenGLView();
// if (!glView)
// {
// return;
// }
// Size frameSize =glView->getFrameSize();
// {
// // Calculate the adjustment ratios based on the old and new projections
// Size size = director->getWinSizeInPixels();
// float widthRatio = size.width / frameSize.width;
// float heightRatio = size.height / frameSize.height;
// //caculate the projections of size change
// Mat4 orthoMatrix;
// Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1, 1, &orthoMatrix);
// director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);
// }
//
// //calculate viewport
// {
// glViewport(0, 0, (GLsizei)(frameSize.width), (GLsizei)(frameSize.height));
// }
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
// 仅在计数为0才更新新的渲染
if (m_nRenderCount == )
{
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureArr[m_nCurTexutreIndex], );
m_nCurTexutreIndex = m_nCurTexutreIndex + < REMIND_RENDER_COUNT ? m_nCurTexutreIndex + : ; glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
} void RemindShader::Render()
{
if (!m_glprogram )
{
return;
} glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
m_glprogram->use();
m_glprogram->setUniformsForBuiltins(); Size sSize = Director::getInstance()->getVisibleSize();
float x = ;
float y = ;
float w = sSize.width;
float h = sSize.height; // 除当前纹理外的纹理存储的都是拖影
int nBeginIndex = m_nCurTexutreIndex;
int nCurIndex = nBeginIndex;
GLfloat falpha = 0.3f;
float addf = 0.05f; // 渲染存在m_pTextureArr队列里的拖影纹理到主场景
do
{
Point delta = _position;// this->convertToWorldSpace(_position);
GLfloat vertices[] = {
x - delta.x,y+ h - delta.y,
x+w - delta.x,y+ h - delta.y,
x - delta.x , y - delta.y,
x+w - delta.x, y - delta.y
};
//GLuint glTexture = m_glprogram->getUniformLocationForName("CC_Texture0");
//glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, m_pTextureArr[nCurIndex]);
//glUniform1i(glTexture, 0);
GL::bindTexture2D(m_pTextureArr[nCurIndex]); GLuint glAlpha = m_glprogram->getUniformLocationForName("u_alpha");
glUniform1f(glAlpha, falpha); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, , GL_FLOAT, GL_FALSE, , ccRenderTextcord);
glDrawArrays(GL_TRIANGLE_STRIP, , ); falpha += addf;
addf += 0.025f;
nCurIndex = ++nCurIndex<REMIND_RENDER_COUNT ? nCurIndex : ;
} while (nCurIndex != nBeginIndex);
//
// GL::bindVAO(0);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void RemindShader::CreateFrameBuffer()
{ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
if (m_nFrameBuffer == )
{
glGenFramebuffers(, &m_nFrameBuffer); if (m_nFrameBuffer == )
{
CCLOG("m_FilterFrameBuffer == 0");
return;
}
}
GLsizei nWidth = m_sRenderSize.width;
GLsizei nHeight = m_sRenderSize.height;
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
if (m_pTextureArr[] == )
{
glGenTextures(REMIND_RENDER_COUNT, m_pTextureArr);
for (int i = ; i < REMIND_RENDER_COUNT; i++)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_pTextureArr[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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);
glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, nWidth, nHeight, , GL_RGBA, GL_UNSIGNED_BYTE, );
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
CCLOG("cocos2d: Texture2D: Error uploading compressed texture glError: 0x%04X", err);
return;
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureArr[i], );
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
}
glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
} void RemindShader::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
if (sRenderChild.size() <= )
{
if (m_nFrameBuffer)
{
// 清理所有缓存的纹理
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
for (int i = ; i < REMIND_RENDER_COUNT; i++)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureArr[i], );
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
}
m_nRenderCount = m_nRenderFrq - ;
return;
}
//Begin will create a render group using new render target
begin(); if (++m_nRenderCount == m_nRenderFrq)
{
//! make sure all children are drawn
auto it = sRenderChild.begin();
while (it != sRenderChild.end())
{
if (Node* node = *it)
{
node->visit(renderer, transform, flags);
node->release();
}
++it;
}
m_nRenderCount = ; // 0 提示需要渲染进去
}
sRenderChild.clear();
//End will pop the current render group
end(); }

几个关键点:

1、利用REMIND_RENDER_COUNT控制需要创建的Texture个数,通过每次绘制到不同的Texture上来保存原来的效果。

2、shader中利用u_alpha参数控制残影的透明度,在render中绘制到原来的FBO上时调用不同的透明度来实现残影渐隐的效果。

3、通过m_nRenderFrq来控制间隔的绘制次数,来实现残影的残留效果远近。

这样就实现了残影的效果了,使用的方法还是跟基类一样。

完整代码地址:https://github.com/mydishes/cocos2dx-Ex/tree/master/Shader

cocos2dx - shader实现任意动画的残影效果的更多相关文章

  1. Unity3D手游开发日记(8) - 运动残影效果

    2D游戏的残影很简单,美术做序列帧图片就行了,那么3D游戏的残影美术做不了,得靠程序员动态创建模型来处理. 实现原理也很简单: 1.间隔一定时间创建一个残影模型 GameObject go = Gam ...

  2. Unity3D-Shader-人物残影效果

    [旧博客转移 - 2016年1月7日 00:24 ] 前面的话 上一篇讲了一下人物边缘发光效果,链接: Unity-ShaderLab-实现X光效果,这次我们利用这个Shader来实现人物残影效果 先 ...

  3. as3如何做出残影效果

    在页游中,时不时能看到人物做一些快速移动动作如冲刺时,有残影效果,强化了画面表现.实际人肉眼之所以能看到残影的效果,是因为观察到的物体会在人视线中残留几十毫秒时间,当运动物体运动太快时,人肉眼所见未能 ...

  4. Unity3d 残影效果(狂拽炫酷叼炸天)

    效果图,真的很叼啊 我根据别人的改进了一版,支持MeshFilter上的Mesh(需要确保Mesh的Read/Write是开启的否则不能正常工作) 非常感谢原作者给提供思路.http://blog.c ...

  5. Unity Shader : Ghost(残影) v1

    前阵子组长给我提了个需求,要实现角色人物的残影.我百度google了一下,发现可以用两种方式实现这个效果:1.记录前几帧的人物位置,将其传入shader中,对每个位置进行一个pass渲染.2. 通过相 ...

  6. Unity运动残影技能

    残影实现: 1.List<DrawMesh> list,此list中包含某一帧动画模型网格.材质 2.每过一段时间就将运动物体的模型add到list中(优化:未实现,网格合并) 3.Lat ...

  7. PS制作gif动图以及背景透明与消除残影

    摘要: 用Photoshop制作gif动画的要点:在窗口菜单中找到“时间轴”选中打开时间轴,单击一帧,设置该帧显示持续时间在图层里将该帧要显示的图层显示,并将不该显示的层隐藏,新建一帧,接下来就是重复 ...

  8. Win7去除桌面残影的方法

    用户升级到Win7系统后使用正常,就是系统桌面会留有残影,怎么样也去不掉,影响用户的使用,那么要如何将这些残影去掉呢?可从计算机属性中进行相关配置. 解决方法 一.在计算机面板上,右键点击“计算机”, ...

  9. HDOJ(HDU) 2153 仙人球的残影(谜一样的题、、、)

    Problem Description 在美丽的HDU,有一名大三的同学,他的速度是众所周知的,跑100米仅仅用了2秒47,在他跑步过程中会留下残影的哎,大家很想知道他是谁了吧,他叫仙人球,既然名字这 ...

随机推荐

  1. FileInputStream 小Demo

    要求:设计如下界面  文本框里面可以输入的路径和文件名  单机按钮可以读取在 指定的文件  并把文件内容显示到一个文本域里面来 代码: /** * */ package com.niit.homewo ...

  2. 201521123052《Java程序设计》第7周学习总结

    1. 本周学习总结 参考资料: XMind 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 public boolean contains(Ob ...

  3. 201521123066《Java程序设计》第十三周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...

  4. 201521123108《Java程序设计》第14周学习总结

    1. 本周学习总结 2. 书面作业 Q1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名) 答: 在自己建立的数据库上执行常见SQL语句(截 ...

  5. 控制结构(6) 最近最少使用(LRU)

    // 上一篇:必经之地(using) // 下一篇:程序计数器(PC) 基于语言提供的基本控制结构,更好地组织和表达程序,需要良好的控制结构. There are only two hard thin ...

  6. allego 输出报告说明

    List of Available Reports Assigned Function Report Lists all assigned functions, sorted by function ...

  7. sqlserver2012 密码过期问题

    昨天登录系统突然连不上数据库了看了看报错内容提示是sqlserver的用户密码过期,那么就简单记录下操作,方便孩子后解决 (1)首先打开sql Management Studio 2012 顺便提一下 ...

  8. SpringMVC第一篇【介绍、入门、工作流程、控制器】

    什么是SpringMVC? SpringMVC是Spring家族的一员,Spring是将现在开发中流行的组件进行组合而成的一个框架!它用在基于MVC的表现层开发,类似于struts2框架 为什么要使用 ...

  9. Jmeter之性能测试基础

    1.概念:性能测试是通过自动化的测试工具模拟多种正常峰值及负载条件来对系统的各项性能指标进行测试.负载测试和压力测试都属于性能测试,两者可以结合进行.通过负载测试,确定在各种工作负载下系统的性能,目标 ...

  10. IIS充当代理转发请求到Kestrel

    接着上篇博文为ASP.NetCore程序启用SSL的code,这篇将介绍如何用IIS充当反向代理的角色转发请求到Kestrel服务器 与ASP.NET不同,ASP.netCore使用的是自托管web服 ...